我一直在经历'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)
{}
那么差异是什么?什么时候应该优先于另一个呢?
答案 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]
无论v
和u
是函数中的变量还是初始化列表中初始化的类的成员,都是如此。
但是在std::initializer_list<T>
构造函数与使用相同数量的参数的普通构造函数重叠的情况之外,没有区别。
答案 2 :(得分:0)
简短描述是:成员初始化列表中的符号与其他地方初始化的变量的符号相匹配。遗憾的是,对它的作用的描述并不容易,因为在构造函数调用中使用花括号有两个有些相互矛盾的变化:
std::initializer_list<T>
而不需要额外的一对括号/花括号。如果构造函数采用std::initializer_list<T>
(对于合适的类型T
),则在使用花括号时使用此构造函数。换句话说,如果有 no std::initializer_list<T>
构造函数,但是其他一些用户定义的构造函数,则使用括号和花括号是等效的。否则它会调用std::initializer_list<T>
构造函数。 ...我猜,我错过了一些细节,因为整个初始化实际上非常复杂。