G.Rassovsky G.Rassovsky - 1 month ago 9
C++ Question

Initializer list syntax in member initializer list (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?

Answer

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.