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

半世苍凉 提交于 2019-11-27 08:59:46

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.

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.

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:

  1. The unified initialization syntax was intended to make to make have all constructions use curly braces and it would just call the corresponding constructor, even if it is the default argument or the type doesn't have a constructor at all and direct initialization is used.
  2. To support variable number of arguments, curly braces can be used to provide an std::initializer_list<T> without an extra pair of parenthesis/curly braces. If there is a constructor taking an std::initializer_list<T> (for a suitable type T) 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 the std::initializer_list<T> constructor. ... and I guess, I'm missing a few details as the entire initialization is actually quite complicated.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!