【发布时间】:2013-05-31 22:41:21
【问题描述】:
【问题讨论】:
-
在这种特殊情况下,最简单的选择是
A a;,对吧?如果我没有误解这一点,那么您建议的语法只有在您要传递给A的构造函数的临时值与A的类型不同时才有意义,对吗? IE。A a { B() };.
标签: c++ c++11 most-vexing-parse
【问题讨论】:
A a;,对吧?如果我没有误解这一点,那么您建议的语法只有在您要传递给A 的构造函数的临时值与A 的类型不同时才有意义,对吗? IE。 A a { B() };.
标签: c++ c++11 most-vexing-parse
这两种语法在大多数情况下是等价的,选择哪一种主要是个人喜好问题。如果您要进行统一初始化,我建议您这样做:
A a{ A{} };
否则,可以单独使用括号来消除歧义:
A a((A())); // This can't be parsed as a function declaration
请注意,有一种情况(我必须说非常不可能)您的问题中显示的两种形式不等价。如果您的类A 有一个采用initializer_list<A> 的构造函数,则在使用大括号时,该构造函数将优于复制构造函数:
#include <initializer_list>
#include <iostream>
struct A
{
A() { }
A(std::initializer_list<A> l) { std::cout << "init-list" << std::endl; }
A(A const& a) { std::cout << "copy-ctor" << std::endl; }
};
int main()
{
A a(A{}); // Prints "copy-ctor" (or nothing, if copy elision is performed)
A b{A()}; // Prints "init-list"
}
上面的区别体现在这个live example中。
【讨论】:
-fno-elide-constructors 在 clang 上是 currently broken。
在大多数情况下,它们是等价的,但A a{ A() }; 会更喜欢std::initializer_list 构造函数(如果存在),而A a( A{} ); 会更喜欢移动/复制构造函数。
当构造最终调用移动/复制构造函数时,可以省略新对象的构造,但这对于 std::initializer_list 构造函数是不可能的。
这两种语法都不会被解析为函数声明,因此都避免了最麻烦的解析。
#include <iostream>
#include <initializer_list>
struct A {
A() {
std::cout << "A()\n";
}
A(A&&) {
std::cout << "A(A&&)\n";
}
A(std::initializer_list<A>) {
std::cout << "A(std::initializer_list<A>)\n";
}
};
int main()
{
{A a{ A() };} // Prints "A()\n" "A(std::initializer_list<A>)\n"
{A a( A{} );} // Prints "A()\n" and *possibly*
// (depending on copy elision) "A(A&&)\n"
}
【讨论】: