[dcl.init.list] (original) (raw)

9 Declarations [dcl.dcl]

9.4 Initializers [dcl.init]

9.4.5 List-initialization [dcl.init.list]

An initializer list may be empty.

List-initialization can occur in direct-initialization or copy-initialization contexts; list-initialization in a direct-initialization context is calleddirect-list-initialization and list-initialization in a copy-initialization context is called copy-list-initialization.

[Note 1:

List-initialization can be used

[Example 1: int a = {1}; std::complex<double> z{1,2};new std::vectorstd::string\{"once", "upon", "a", "time"}; f( {"Nicholas","Annemarie"} ); return { "Norah" }; int* e {}; x = double{1}; std::mapstd::string,int\ anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} }; — _end example_]

— _end note_]

A constructor is an initializer-list constructor if its first parameter is of type std​::​initializer_­list<E> or reference tocv std​::​initializer_­list<E> for some type E, and either there are no other parameters or else all other parameters have default arguments ([dcl.fct.default]).

[Note 2:

Initializer-list constructors are favored over other constructors in list-initialization ([over.match.list]).

Passing an initializer list as the argument to the constructor template template<class T> C(T) of a class C does not create an initializer-list constructor, because an initializer list argument causes the corresponding parameter to be a non-deduced context ([temp.deduct.call]).

— _end note_]

The templatestd​::​initializer_­list is not predefined; if the header<initializer_­list> is not imported or included prior to a use ofstd​::​initializer_­list — even an implicit use in which the type is not named ([dcl.spec.auto]) — the program is ill-formed.

List-initialization of an object or reference of type T is defined as follows:

That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clausethat follows it in the comma-separated list of the initializer-list.

[Note 4:

This evaluation ordering holds regardless of the semantics of the initialization; for example, it applies when the elements of theinitializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call.

— _end note_]

An object of type std​::​initializer_­list<E> is constructed from an initializer list as if the implementation generated and materialized ([conv.rval]) a prvalue of type “array of N const E”, where N is the number of elements in the initializer list.

Each element of that array is copy-initialized with the corresponding element of the initializer list, and thestd​::​initializer_­list<E> object is constructed to refer to that array.

[Note 5:

A constructor or conversion function selected for the copy is required to be accessible ([class.access]) in the context of the initializer list.

— _end note_]

If a narrowing conversion is required to initialize any of the elements, the program is ill-formed.

[Example 12: struct X { X(std::initializer_list<double> v);}; X x{ 1,2,3 };

The initialization will be implemented in a way roughly equivalent to this:const double __a[3] = {double{1}, double{2}, double{3}}; X x(std::initializer_list<double>(__a, __a+3));assuming that the implementation can construct an initializer_­list object with a pair of pointers.

— _end example_]

The array has the same lifetime as any other temporary object ([class.temporary]), except that initializing aninitializer_­list object from the array extends the lifetime of the array exactly like binding a reference to a temporary.

[Example 13: typedef std::complex<double> cmplx; std::vector<cmplx> v1 = { 1, 2, 3 };void f() { std::vector<cmplx> v2{ 1, 2, 3 }; std::initializer_list<int> i3 = { 1, 2, 3 };} struct A { std::initializer_list<int> i4; A() : i4{ 1, 2, 3 } {} };

For v1 and v2, the initializer_­list object is a parameter in a function call, so the array created for{ 1, 2, 3 } has full-expression lifetime.

For i3, the initializer_­list object is a variable, so the array persists for the lifetime of the variable.

For i4, the initializer_­list object is initialized in the constructor's ctor-initializer as if by binding a temporary array to a reference member, so the program is ill-formed ([class.base.init]).

— _end example_]

[Note 6:

The implementation is free to allocate the array in read-only memory if an explicit array with the same initializer could be so allocated.

— _end note_]

A narrowing conversion is an implicit conversion

[Note 7:

As indicated above, such conversions are not allowed at the top level in list-initializations.

— _end note_]

[Example 14: int x = 999; const int y = 999;const int z = 99;char c1 = x; char c2{x}; char c3{y}; char c4{z}; unsigned char uc1 = {5}; unsigned char uc2 = {-1}; unsigned int ui1 = {-1}; signed int si1 = { (unsigned int)-1 }; int ii = {2.0}; float f1 { x }; float f2 { 7 }; bool b = {"meow"}; int f(int);int a[] = { 2, f(2), f(2.0) }; — _end example_]