{}构造语法的通用性如何

How generic is the {} construction syntax?

本文关键字:通用性 语法      更新时间:2023-10-16

在一次关于初始化列表的讨论中,我理解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>'

请注意,当我用int替换X时,它是有效的。

Brace初始化在使用初始化器的任何地方都有效。在某些情况下,必须使用parens才能访问大括号初始值设定项无法访问的构造函数,但这种情况很少见。

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

vector<int>恰好有一个占用两个int秒的专用构造函数,因此在试图构造两个int秒长的向量时是不明确的。存在不明确的构造函数只是为了向后兼容。不应使用任何与initializer_list冲突的构造函数来定义新类。

大括号初始化语法更喜欢initializer_list构造函数,而不是其他匹配的构造函数,这一事实解决了歧义。如果您想通过使用noninitializer_list构造函数来解决歧义,那么就不能使用大括号初始化。


Bjarne Stroustrup写入

只有在C++11中才能统一使用{}初始化,因此较旧的C++代码使用()和=initialization。因此,您可能更熟悉()和=。然而,我不知道有什么逻辑原因更喜欢()表示法,除非在极少数情况下,您需要区分使用元素列表的初始化和构造函数参数列表的初始化。

nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp mdashC++编程语言,第四版§17.3.2.1


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