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?
The short description is: the notation in the member initializer list matches that of variables initialized elsewhere. Sadly, the description of what it does is not as easy at all because there are two somewhat conflicting changes relating to the use of curly braces for constructor calls:
std::initializer_list<T>
without an extra pair of parenthesis/curly braces. If there is a constructor taking anstd::initializer_list<T>
(for a suitable typeT
) this constructor is used when using curly braces.Put differently, if there is no
std::initializer_list<T>
constructor but some other user defined constructor the use of parenthesis and curly braces is equivalent. Otherwise it calls thestd::initializer_list<T>
constructor. ... and I guess, I'm missing a few details as the entire initialization is actually quite complicated.There can be a difference in a few really annoying edge cases:
That is true regardless of whether
v
andu
are just variables in a function or are members of a class initialized in an initialization list.But outside the cases where a
std::initializer_list<T>
constructor overlaps with a normal constructor taking the same number of arguments, there is no 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: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: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.