Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 576
G.Rassovsky Avatar asked Dec 11 '22 02:12

G.Rassovsky


2 Answers

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.

like image 190
Mike Seymour Avatar answered Dec 31 '22 01:12

Mike Seymour


There can be a difference in a few really annoying edge cases:

std::vector<int> v{3, 2}; // constructs a vector containing [3, 2]
std::vector<int> u(3, 2); // constructs a vector containing [2, 2, 2]

That is true regardless of whether v and u 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.

like image 45
Barry Avatar answered Dec 31 '22 00:12

Barry