list initialization (since C++11) - cppreference.com

##### cppreference.com

##### Search

Create account

##### Namespaces

- Page
- Discussion

##### Variants

##### Views

- View
- Edit
- History

##### Actions

# list initialization (since C++11)

From cppreference.com
< cpp‎ | language

Initializes an object from braced-init-list

### [edit] Syntax

T object `{` arg1, arg2, ... `};` | (1) |
T `{` arg1, arg2, ... `};` | (2) |
`new` T `{` arg1, arg2, ... `};` | (3) |
`return {` arg1, arg2, ... `} ;` | (4) |
function`( {` arg1, arg2, ... `} ) ;` | (5) |
object`[ {` arg1, arg2, ... `} ] ;` | (6) |
T`( {` arg1, arg2, ... `} )` | (7) |
Class `{` T member `=` `{` arg1, arg2, ... `}; };` | (8) |
Class`::`Class`() :` member`{`arg1, arg2, ...`} {...` | (9) |
T object `= {`arg1, arg2, ...`};` | (10) |

### [edit] Explanation

List initialization is performed in the following situations:

1) initialization of a named variable with a brace-enclosed list of expressions or nested lists (braced-init-list)
2) initialization of an unnamed temporary with a braced-init-list
3) initialization of an object with dynamic storage duration with a new-expression, where the initializer is a brace-init-list
4) in a return statement with braced-init-list used as the return expression
5) in a function call expression, with braced-init-list used as an argument
6) in a subscript expression with a user-defined operator[]
7) in a functional cast expression or other direct-initialization, with braced-init-list used as the constructor argument
8) in a non-static data member initializer
9) in a constructor initializer list
10) on the right-hand-side of the equals sign (similar to copy-initialization)

The effects of list initialization of an object of type `T` are:

If the braced-init-list is empty and `T` is a class type with a default constructor, value-initialization is performed. Otherwise, if `T` is an aggregate type, aggregate initialization is performed. | (until C++14)
If `T` is an aggregate type, aggregate initialization is performed. Otherwise, If the braced-init-list is empty and `T` is a class type with a default constructor, value-initialization is performed. | (since C++14)

- Otherwise, if `T` is a specialization of std::initializer_list, a new `std::initializer_list` prvalue of the same type is constructed and used to direct-initialize or copy-initialize the object of type `T`, depending on context.

- Otherwise, the constuctors 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 type std::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)

- 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 or copy-initialized, depending on context, 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.

### [edit] 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 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

### [edit] Notes

Braced-init-list is not an expression and has no type on its own: decltype({1,2}) is illegal. A special exception is made for the keyword auto, which deduces any braced-init-list as std::initializer_list.

### [edit] Example

Run this code

    #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

### [edit] See also

- default initialization
- direct initialization
- aggregate initialization
- copy initialization

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/language/list_initialization&oldid=71840"