language_list_initialization

language_list_initialization (리스트 초기화, 중괄호 초기화)

중괄호로 감싼 초기화자 목록(braced-init-list)으로 객체를 초기화해요. C++11부터 도입된, 가장 다재다능하고 좁히기 변환을 막아주는 초기화 방식이에요.

출처: cppreference

본문

문법

직접 리스트 초기화 (Direct-list-initialization)

T object { arg1, arg2, ... };                      // (1)
T object {.des1 = arg1 , .des2 { arg2 } ... };     // (1) since C++20
T { arg1, arg2, ... }                              // (2)
T {.des1 = arg1 , .des2 { arg2 } ... }             // (2) since C++20
new T { arg1, arg2, ... }                          // (3)
new T {.des1 = arg1 , .des2 { arg2 } ... }         // (3) since C++20
Class { T member { arg1, arg2, ... }; };           // (4)
Class { T member {.des1 = arg1 , .des2 { arg2 } ... }; };  // (4) since C++20
Class::Class() : member { arg1, arg2, ... } {...}  // (5)
Class::Class() : member {.des1 = arg1 , .des2 { arg2 } ...} {...} // (5) since C++20

복사 리스트 초기화 (Copy-list-initialization)

T object = { arg1, arg2, ... };                    // (6)
T object = {.des1 = arg1 , .des2 { arg2 } ... };   // (6) since C++20
function ({ arg1, arg2, ... })                     // (7)
function ({.des1 = arg1 , .des2 { arg2 } ... })    // (7) since C++20
return { arg1, arg2, ... };                        // (8)
return {.des1 = arg1 , .des2 { arg2 } ... };       // (8) since C++20
object [{ arg1, arg2, ... }]                       // (9)
object [{.des1 = arg1 , .des2 { arg2 } ... }]      // (9) since C++20
object = { arg1, arg2, ... }                       // (10)
object = {.des1 = arg1 , .des2 { arg2 } ... }      // (10) since C++20
U ({ arg1, arg2, ... })                            // (11)
U ({.des1 = arg1 , .des2 { arg2 } ... })           // (11) since C++20
Class { T member = { arg1, arg2, ... }; };         // (12)
Class { T member = {.des1 = arg1 , .des2 { arg2 } ... }; }; // (12) since C++20

설명

리스트 초기화는 다음 상황에서 수행돼요.

  • 직접 리스트 초기화: 중괄호 목록으로 직접 초기화. explicit·비-explicit 생성자 모두 사용 가능.
  • 복사 리스트 초기화: = 뒤 중괄호 목록으로 초기화. explicit 생성자는 사용할 수 없어요.

리스트 초기화의 핵심은 좁히기 변환(narrowing conversion) 금지예요. 예를 들어 doubleint 초기화에 넣으면 컴파일 오류가 나요. 또, 생성자 오버로드 해석에서 std::initializer_list 생성자가 다른 생성자보다 우선해요.

int x { 3.14 };   // 오류: 좁히기 변환
std::vector<int> v{1, 2, 3};  // initializer_list 생성자 사용

C++20부터 지정 초기화(designated initializer)로 멤버 이름을 지정해 초기화할 수도 있어요.

더 알아보기 (Learn more)

cppreference