6

在一次关于初始化列表的讨论中,我理解 Stroustrup 基本上是说带有花括号的新构造语法应该是对所有以前的构造语法的一般替代:

X x1(); // most vexing parse ... doesn't work as intended
X x2(x1);
X x3 = x1;
X x4 = X();

相反,新语法应该被统一使用,作为一种可能的替代品,你可以在任何情况下使用……再说一次,这是我从他的演讲中得到的核心信息。也许我误解了他。

所以,问题是,这种语法有多通用?是否有可能永远不要在新的 C++11 代码中使用旧式构造,或者是否存在必须恢复的情况?


当我遇到以下错误时触发/激发了这个问题,我认为这是编译器中的错误(但我很乐意得到纠正)。

struct X {};

int main() {
  X x;
  X& y{x}; // works with (x)
  X& z{y}; // works with (y)
}

它不能在 g++ 4.7.1 上编译,也不能在ideone 的 4.5.1上编译。

prog.cpp: In function 'int main()':
prog.cpp:5:9: error: invalid initialization of non-const reference of type 'X&' from an rvalue of type '<brace-enclosed initializer list>'
prog.cpp:6:9: error: invalid initialization of non-const reference of type 'X&' from an rvalue of type '<brace-enclosed initializer list>'

请注意,当我替换Xint.

4

1 回答 1

9

大括号初始化适用于使用初始化程序的任何地方。在某些情况下,您必须使用括号才能访问大括号初始值设定项无法访问的构造函数,但这种情况很少见。

std::vector<int> v(1,1);
std::vector<int> v{1,1};

vector<int>碰巧有一个专门的构造函数,它需要两个ints,因此在尝试构造一个两个ints 长的向量时会模棱两可。模棱两可的构造函数的存在只是为了向后兼容。不应使用与 initializer_list 冲突的任何构造函数来定义新类。

大括号初始化语法更喜欢 initializer_list 构造函数而不是其他匹配的构造函数,从而解决了歧义。如果您想解决歧义以支持使用 non-initializer_list 构造函数,那么您不能使用大括号初始化。


Bjarne Stroustrup 写道

{} 初始化的统一使用仅在 C++11 中成为可能,因此较旧的 C++ 代码使用 () 和 = 初始化。因此,您可能更熟悉 () 和 =。但是,我不知道有任何逻辑理由更喜欢 () 表示法,除非在极少数情况下需要区分使用元素列表和构造函数参数列表进行初始化。

                                                         — C++ 编程语言,第四版§17.3.2.1


您的示例代码完全合法,应该可以按预期工作。您得到的错误只是 GCC 中的一个错误。Clang 和 VC++ 2012 都接受该代码。

于 2012-09-16T20:03:37.320 回答