c++ 유니폼 초기화
유니폼 초기화
C++11 이전에는 타입의 초기화 방식이 일정하지 않았다. 예를 들어 다음과 같이 원을 정의할 때 한 번은 구조체로, 한 번은 클래스로 작성한 경우를 살펴보자 구조체에 대해서는 {...} 문법을 적용한 반면, 클래스에 대해서는 함수 표기법인 (...)로 생성자를 호출했다. C++11부터 타입을 초기화할 때 {...} 문법을 사용하는 유니폼 초기화(uniform Initialization - 균일 초기화, 중괄호 초기화)를 따르도록 통일됐다. 그렇다면! 이렇게 가능하다는 말이다. myCircle4를 정의하는 문장이 실행 될 때 CircleClass의 생성자가 자동으로 호출된다. 물론 등호를 생략해도 좋다!C++ 모든 대상
이러한 uniform initializer는 구조체나 클래스뿐만 아니라 C++의 모든 대상을 초기화 하는데 사용 될 수 있다. 물론 유니폼 초기화로 영 초기화(zero initialization)를 할 때도 적용 가능하다. 아래와 같다.축소 변환
유니폼 초기화를 사용하면 축소 변환 (narrow - 좁히기)을 방지할 수 있다. C++ 에서는 암묵적으로 축소 변활될 때가 있는데, 예를 들면 다음과 같다.x
에 값을 대입할 때와 func()
를 호출할 때 전달한 1.234는 3으로 값이 줄어든다. 물론 컴파일러가 요놈을 잡았다! 라고 알려줄 경고 메세지를 날려 주기도 한다.
/Users/colson/workspace/colson-log/c,c++/uniform initialization/ex2.cpp:18:14: warning: implicit conversion from 'double' to 'int' changes value from 1.2345 to 1 [-Wliteral-conversion]
int x = 1.2345;
~ ^~~~~~
/Users/colson/workspace/colson-log/c,c++/uniform initialization/ex2.cpp:19:11: warning: implicit conversion from 'double' to 'int' changes value from 1.1234 to 1 [-Wliteral-conversion]
func(1.1234);
~~~~ ^~~~~~
2 warnings generated.
그렇다면 유니폼 초기화를 사용하여 값을 대입하거나 함수를 호출할 때는 어떻게 될까? 답은 아래와 같다.
유니폼 초기화를 사용하는 코드는 축소로 인한 변환이 있으면 반드시 에러를 발생시킨다.
동적 배열 초기화
동적으로 할당되는 배열을 초기화할 때도 적용할 수 있다. 또한 클래스 멤버인 배열을 생성자 이니셜라이저로 초기화할 때도 사용될 수 있다.리스트 초기화
이니셜라이져는 두가지가 있다. 이니셜라이져 리스트를 중괄호로 묵어서 표현한다.-
복제 리스트 초기화(copy list initialization):
obj = {arg1, arg2, ...};
-
직접 리스트 초기화(direct list initialization):
T obj {arg1, arg2, ...};
NOTE_ 복제 리스트 초기화에서 중괄호 안에 나온 원소는 반드시 타입이 모두 같아야 한다.
auto b = {11, 1.1234}
과 같은 코드를 작성하면 에러가 뿜뿜한다.
참고
- code example
- 전문가를 위한 C++