Search code examples
c++c++11initializer-listmember-initialization

Initializer list syntax in member initializer list using C++11


I've been going through 'A Tour of C++' and Bjarne uses the the c++11 initializer list feature in member initialization in a constructor, like so (using curly brackets):

A a;
B b;
Foo(Bar bar):
  a{bar.a}, b{bar.b}
{}

This, however doesn't compile prior to c++11. What is the difference with the old member initializer list (using round brackets):

Foo(Bar bar):
  a(bar.a), b(bar.b)
{}

So what is the difference and when should one be preferred over the other?


Solution

  • So what is the difference?

    Round brackets only work for non-class types, or types with a suitable constructor for the number of arguments in the brackets.

    Squiggly braces work for these, and also for aggregates - simple struct or array types with no constructor. So the following will work:

    struct {
        int a,b;
    } aggregate;
    int array[2];
    
    Foo() : aggregate{1,2}, array{3,4} {}
    

    Finally, braces will match a constructor taking a suitably-typed initializer_list, rather than a constructor with parameter(s) to match the arguments. For example:

    std::vector<int> v1;
    std::vector<int> v2;
    
    Foo() :
        v1(10,2),   // 10 elements with value 2
        v2{10,2}    // 2 elements with value 10,2
    {}
    

    when should one be preferred over the other?

    Prefer round brackets if you want to make it clearer that the initialisation is using a constructor rather than aggregate or initializer_list; or to force use of a specific constructor.

    Prefer braces when you need a form of initialisation not otherwise supported; or when you just want the initialisation to "do the right thing".

    In the cases where both do the same thing, the choice is largely aesthetic.