대입과 초기화
대입 (Assignment)
대입은 =
대입 연산자를 사용하여 어떤 변수에 값을 지정하는 것이다. 이를 "copy assignment"라고도 하는데, 그 이유는 대입은 등호 왼쪽의 객체(변수)에 등호 오른쪽의 값을 복사하는 행위이기 때문이다. 하지만 그렇기 때문에 연산자 왼쪽의 객체(변수)가 이미 정의/생성되어 있어야 한다.
초기화 (Initialization)
반면, 초기화는 객체의 생성과 함께 최초의 설정값을 지정하는 것이다. 따라서 함수 호출의 회수가 대입에 비해 적으며 더 빠르기도 하다. 초기화로는 상수(const) 변수의 값 설정 또한 가능하다.
초기화의 방식
class Point
{
public:
Point(int x_val, int y_val)
{
x = x_val; y = y_val;
}
private:
int x;
int y;
};
Copy Initialization
Point p1 = { 0, 1 };
등호(=
)를 사용한 초기화이다. 대입과 마찬가지로 등호 오른쪽의 값을 등호 왼쪽의 객체(변수)에 복사한다. int
와 같이 단순한 타입의 변수에는 문제없으나, 타입이 복잡해지면 복사의 방식이 비효율적이다.
Direct Initialization
Point p2( 2, 3 );
소괄호(( )
)를 사용한 초기화이다. 단순한 타입의 초기화에는 copy initialization와 다를 바 없으나, 복잡한 타입의 초기화에는 direct initialization이 더 효율적이다.
Brace Initialization (Uniform Initialization)
Point p3 { 4, 5 };
중괄호({ }
)를 사용한 초기화이다.
소괄호를 사용한 direct initialization은 모든 데이터 타입을 초기화 하는데에 사용할 수 없다. 따라서 C++에서는 모든 형태의 변수를 초기화 할 수 있는, uniform initialization을 통한 초기화 방법을 제공한다.
int main(void)
{
int v1 = 0;
int v2{ 1 };
int v3( 2 );
int arr_v1[2] = { 0, 1 };
int arr_v2[2]{ 2, 3 };
int arr_v3[2]( 4, 5 );
return 0;
}
main.cpp:11:6: error: array initializer must be an initializer list
int arr_v3[2]( 4, 5 );
^
1 error generated.
Uniform Initialization
초기화의 형태
uniform initialization의 사용은 크게 3가지 형태로 구분된다.
1) direct brace initialization (권장)
int var { 0 };
2) copy brace initialization
int var = { 0 };
3) value initialization
int var { }; // value initialization
value initialization은 인자 없는 생성자를 호출하며 객체를 생성한다. 따라서, 컴파일러가 제공하는 default 생성자 또는 사용자가 직접 정의한, 인자가 없는 생성자를 호출할 수 있어야 한다.
class t1
{
private:
int var;
}; // implicit default constructor
class t2
{
public:
t2() { } // user-provided default constructor
private:
int var;
};
class t3
{
public:
// no default constructor
t3(int val) { var = val; }
private:
int var;
};
int main(void)
{
t1 var1{ };
t2 var2{ };
t3 var3{ };
}
main.cpp:27:5: error: no matching constructor for initialization of 't3'
t3 var3{ };
^ ~~~
1 error generated.
데이터 손실의 방지
uniform initialization은 또 다른 기능도 있다. 바로 "preventing narrowing conversion"이다. 이는 결국 어떤 변수에 해당 변수가 저장할 수 있는 크기보다 더 큰 크기의 데이터를 저장하여 일부 데이터의 손실이 발생하는 것을 방지한다.
int main(void)
{
int var { 4.5 };
}
main.cpp:3:12: error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
int var { 4.5 };
^~~
1 warning and 1 error generated.
References
・ https://en.cppreference.com/w/cpp/language/value_initialization
・ https://www.learncpp.com/cpp-tutorial/variable-assignment-and-initialization/
'C · C++' 카테고리의 다른 글
[C++] 함수의 선언과 구현부 분리 (0) | 2022.07.13 |
---|---|
[C++] 생성자와 초기화 리스트 (Initializer List) (0) | 2022.05.26 |
[C++] 구조체(struct)와 클래스(class) (2) | 2022.05.15 |
[C(++)] Header Guard (헤더 가드) Coding (0) | 2022.02.05 |
[C] printf 함수 (0) | 2021.12.21 |