使用C ++ 11在成员初始化列表中的初始化列表语法

时间:2014-11-07 15:16:10

标签: c++ c++11 initializer-list member-initialization

我一直在经历'A Tour of C++',Bjarne在构造函数中使用成员初始化中的c ++ 11初始化列表功能,就像这样(使用大括号):

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

然而,这不会在c ++ 11之前编译。与旧成员初始化列表有什么区别(使用圆括号):

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

那么差异是什么?什么时候应该优先于另一个呢?

3 个答案:

答案 0 :(得分:8)

  

那有什么区别?

圆括号仅适用于非类类型,或者对于括号中的参数数量具有合适构造函数的类型。

Squiggly大括号适用于这些,也适用于聚合 - 简单struct或没有构造函数的数组类型。所以以下内容将起作用:

struct {
    int a,b;
} aggregate;
int array[2];

Foo() : aggregate{1,2}, array{3,4} {}

最后,大括号将匹配采用适当类型initializer_list的构造函数,而不是带有参数的构造函数来匹配参数。例如:

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
{}
  

什么时候应该优先于另一个呢?

如果你想更清楚地说初始化是使用构造函数而不是聚合或initializer_list,那么更喜欢圆括号;或强制使用特定的构造函数。

当您需要一种不支持的初始化形式时,首选大括号;或者当你只是想要初始化“做正确的事”时。

在两者都做同样事情的情况下,选择主要是审美。

答案 1 :(得分:2)

可能在一些真正恼人的边缘情况中存在差异:

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]

无论vu是函数中的变量还是初始化列表中初始化的类的成员,都是如此。

但是在std::initializer_list<T>构造函数与使用相同数量的参数的普通构造函数重叠的情况之外,没有区别。

答案 2 :(得分:0)

简短描述是:成员初始化列表中的符号与其他地方初始化的变量的符号相匹配。遗憾的是,对它的作用的描述并不容易,因为在构造函数调用中使用花括号有两个有些相互矛盾的变化:

  1. 统一初始化语法意图使得所有构造都使用大括号,它只会调用相应的构造函数,即使它是默认参数或该类型根本没有构造函数,并且使用了直接初始化。
  2. 为了支持可变数量的参数,可以使用花括号来提供std::initializer_list<T>而不需要额外的一对括号/花括号。如果构造函数采用std::initializer_list<T>(对于合适的类型T),则在使用花括号时使用此构造函数。
  3. 换句话说,如果有 no std::initializer_list<T>构造函数,但是其他一些用户定义的构造函数,则使用括号和花括号是等效的。否则它会调用std::initializer_list<T>构造函数。 ...我猜,我错过了一些细节,因为整个初始化实际上非常复杂。