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 (only non-explicit constructors may be called)
return
statement with braced-init-list used as the return expression and list-initialization initializes the returned objectoperator[]
, 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
T
is a specialization ofstd::initializer_list
, a newstd::initializer_list
prvalue of the same type is constructed and used to direct-initialize or copy-initialize the object of typeT
, depending on context. - Otherwise, the constructors of
T
are 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 typestd::initializer_list
- If the previous stage does not produce a match, all constructors of
T
participate 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)
- All constructors that take
- Otherwise, if the braced-init-list has only one element and either
T
isn't a reference type or is reference type that isn't compatible with the type of the element,T
is direct-initialized (in direct-list-initialization) or copy-initialized (in copy-list-initialization), except that narrowing conversions are not allowed. - Otherwise, if
T
is reference type, a prvalue temporary of the referenced type is list-initialized, and the reference is bound to that temporary. (this fails if the reference is a non-const lvalue reference) - Otherwise, if the braced-init-list has no elements,
T
is 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
todouble
or tofloat
and conversion fromdouble
tofloat
, 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
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. 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.
Example
#include <iostream> #include <vector> #include <map> #include <string> struct Foo { std::vector<int> mem = {1,2,3}; // list-initialization of a non-static member std::vector<int> mem2; Foo() : mem2{-1, -2, -3} {} // list-initialization of a member in constructor }; std::pair<std::string, std::string> f(std::pair<std::string, std::string> p) { return {p.second, p.first}; // list-initialization in return statement } int main() { int n0{}; // value-initialization (to zero) int n1{1}; // direct-list-initialization std::string s1{'a', 'b', 'c', 'd'}; // initializer-list constructor call std::string s2{s1, 2, 2}; // regular constructor call std::string s3{0x61, 'a'}; // initializer-list ctor is preferred to (int, char) int n2 = {1}; // copy-list-initialization double d = double{1.2}; // list-initialization of a temporary, then copy-init std::map<int, std::string> m = { // nested list-initialization {1, "a"}, {2, {'a', 'b', 'c'} }, {3, s1} }; std::cout << f({"hello", "world"}).first // list-initialization in function call << '\n'; const int (&ar)[2] = {1,2}; // binds a lvalue reference to a temporary array int&& r1 = {1}; // binds a rvalue reference to a temporary int // int& r2 = {2}; // error: cannot bind rvalue to a non-const lvalue ref // int bad{1.0}; // error: narrowing conversion unsigned char uc1{10}; // okay // unsigned char uc2{-1}; // error: narrowing conversion Foo f; std::cout << n0 << ' ' << n1 << ' ' << n2 << '\n' << s1 << ' ' << s2 << ' ' << s3 << '\n'; for(auto p: m) std::cout << p.first << ' ' << p.second << '\n'; for(auto n: f.mem) std::cout << n << ' '; for(auto n: f.mem2) std::cout << n << ' '; }
Output:
world 0 1 1 abcd cd aa 1 a 2 abc 3 abcd 1 2 3 -1 -2 -3
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1467 | C++14 | same-type initialization of aggregates and char arrays was prohibited | same-type initialization allowed |
Please login to continue.