list initialization (since C++11)
Initializes an object from braced-init-list
Syntax
direct-list-initialization
T object { arg1, arg2, ... };
|
(1) | ||||||||
T { arg1, arg2, ... };
|
(2) | ||||||||
new T { arg1, arg2, ... }
|
(3) | ||||||||
Class { T member { arg1, arg2, ... }; };
|
(4) | ||||||||
Class::Class() : member{arg1, arg2, ...} {...
|
(5) | ||||||||
copy-list-initialization
T object = {arg1, arg2, ...};
|
(6) | ||||||||
function( { arg1, arg2, ... } ) ;
|
(7) | ||||||||
return { arg1, arg2, ... } ;
|
(8) | ||||||||
object[ { arg1, arg2, ... } ] ;
|
(9) | ||||||||
object = { arg1, arg2, ... } ;
|
(10) | ||||||||
U( { arg1, arg2, ... } )
|
(11) | ||||||||
Class { T member = { arg1, arg2, ... }; };
|
(12) | ||||||||
List initialization is performed in the following situations:
- direct-list-initialization (both explicit and non-explicit constructors are considered)
- copy-list-initialization (both explicit and non-explicit constructors are considered, but only non-explicit constructors may be called)
operator[], where list-initialization initializes the parameter of the overloaded operatoroperator= Explanation
The effects of list initialization of an object of type T are:
|
(since C++14) |
|
(until C++14) |
|
(since C++14) |
- Otherwise, if
Tis a specialization of std::initializer_list, theTobject is direct-initialized or copy-initialized, depending on context, from a prvalue of the same type initialized from (until C++17) the braced-init-list.
- Otherwise, the constructors of
Tare considered, in two phases:
- All constructors that take std::initializer_list as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of type std::initializer_list
- If the previous stage does not produce a match, all constructors of
Tparticipate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all).
- If the previous stage does not produce a match, all constructors of
|
(since C++17) |
- Otherwise (if
Tis not a class type), if the braced-init-list has only one element andeitherTisn't a reference type or is a reference type that is compatible with the type of the element,Tis direct-initialized (in direct-list-initialization) or copy-initialized (in copy-list-initialization), except that narrowing conversions are not allowed.
- Otherwise, if
Tis a reference type that isn't compatible with the type of the element, a temporary of the referenced type is list-initialized, and the reference is bound to that temporary (until C++17)the reference is direct-initialized from a prvalue expression of the referenced type that list-initializes its result object (since C++17). (this fails if the reference is a non-const lvalue reference)
- Otherwise, if the braced-init-list has no elements,
Tis value-initialized.
Narrowing conversions
list-initialization limits the allowed implicit conversions by prohibiting the following:
- conversion from a floating-point type to an integer type
- conversion from a long double to double or to float and conversion from double to float, except where the source is a constant expression and overflow does not occur
- conversion from an integer type to a floating-point type, except where the source is a constant expression whose value can be stored exactly in the target type
- conversion from integer or unscoped enumeration type to integer type that cannot represent all values of the original, except where source is a constant expression whose value can be stored exactly in the target type
Notes
Every initializer clause is sequenced before any initializer clause that follows it in the braced-init-list. This is in contrast with the arguments of a function call expression, which are unsequenced.
A braced-init-list is not an expression and therefore has no type, e.g. decltype({1,2}) is ill-formed. Having no type implies that template type deduction cannot deduce a type that matches a braced-init-list, so given the declaration template<class T> void f(T); the expression f({1,2,3}) is ill-formed. However, the template parameter can otherwise be deduced, as is the case for std::vector<int> v(std::istream_iterator<int>(std::cin), {}), where the iterator type is deduced by the first argument but also used in the second parameter position. A special exception is made for type deduction using the keyword auto , which deduces any braced-init-list as std::initializer_list.
Also because braced-init-list has no type, special rules for overload resolution apply when it is used as an argument to an overloaded function call.
|
Aggregates copy/move initialize directly from single-element braced-init-lists of the same type, but non-aggregates consider initializer_list constructors first: struct X { X() = default; X(const X&) = default; }; struct Q { Q() = default; Q(Q const&) = default; Q(std::initializer_list<Q>) {} }; int main() { X x; X x2 = X { x }; // copy-constructor (not aggregate initialization) Q q; Q q2 = Q { q }; // initializer-list constructor (not copy constructor) } |
(since C++14) |