C++11에 유니폼 초기화가 추가되었다. {}를 이용한 초기화여서 Brace-Initialization 이라고도 부른다.
struct A
{
int x, y;
};
class B
{
public:
B(int x, int y) : mX(x), mY(y) {}
private:
int mX, mY;
};
A a = {10, 20}; // {}
B b(10, 20); // ()
int c[4] = {1, 2, 3, 4}; // {}
C++11에서는 이 부분을 모두 {}를 이용하는 유니폼 초기화로 문법을 통일시켰다, =을 붙이거나 붙이지 않거나 모두 유니폼 초기화를 사용할 수 있다.
A a1 = {10, 20};
B b1 = {10, 20};
A a2{10, 20};
B b2{10, 20};
유니폼 초기화는 일반 자료형에도 사용 가능하다. 아래 예제에서 {}로 초기화할 경우 0이 들어간다.
int a = 1;
int b(1);
// uniform-initialization
int c = {1};
int d{1};
int e{}; // 0
한가지 기능을 더 추가하였는데 바로 축소 변환 방지(narrowing) 기능이다. 이는 암묵적 캐스팅이 진행될 때 기존 데이터의 손실이 발생할 경우 에러를 처리해주는 기능을 말한다. 예를 들자면 int에 double 값을 넣을 경우에 소수부분은 손실되게 되는데 이러한 상황을 막는 것이다.
void PrintInt(int x)
{
std::cout << "Num : " << x << std::endl;
}
A i { 3.14, 3.14 }; // warning
B j { 3.14, 3.14 }; // error
int k { 3.14 }; // error
PrintInt(3.14); // warning
PrintInt({ 3.14 }); // error
a = {}와 같은 형태를 복제 리스트 초기화라고 하고 a {}와 같은 형태를 직접 리스트 초기화라고 한다. {}를 auto로 받았을 경우에 타입이 무엇이냐에 대한 것이다. {}를 auto로 받으면 initializer_list<>으로 변경되고 처리가 되는데 C++17 이전과 이후에 약간 변화가 있다.
// before C++ 17
auto a1 = { 1 }; // initializer_list<int>
auto a2 = { 1, 2 }; // initializer_list<int>
auto a3{ 1 }; // initializer_list<int>
auto a4{ 1, 2 }; // initializer_list<int>
auto a5 = { 1, 1.1 }; // error
// after C++ 17
auto a1 = { 1 }; // initializer_list<int>
auto a2 = { 1, 2 }; // initializer_list<int>
auto a3{ 1 }; // int
auto a4{ 1, 2 }; // error
auto a5 = { 1, 1.1 }; // error
C++17 이후 a4의 경우에는 초기화 리스트가 아닌 타입을 추론하게 되는데 이때 하나의 값에 의한 추론만 진행하기 때문에 값이 여러개라고 에러가 발생하게 된다. 그리고 a5의 경우에는 복제 초기화 리스트라도 다른 타입의 값을 넘긴다면 추론에 실패한다.
출처: https://msparkms.tistory.com/entry/C-유니폼-초기화-Uniform-Initializer [MSPark's Blog:티스토리]
'프로그래밍 언어 > C++' 카테고리의 다른 글
C++ 캐스팅 static_cast / reinterpret_cast 예제 (0) | 2022.06.10 |
---|---|
C++ SFINAE 여러 타입에 대응하는 템플릿 오버로딩 (0) | 2022.06.10 |
C++ 콜백 CallBack 함수 (0) | 2022.06.09 |
C++ 함수 객체 (Fuction Object) 템플릿 / 람다식 (0) | 2022.06.06 |
C++ 11 버전 주 기능 (0) | 2022.06.05 |