最烦人的解析 C++11
Most vexing parse C++11
我对 Y y {X{}};
这行代码到底做了什么以及它与最令人烦恼的解析有什么联系感到困惑。一个简短的解释表示赞赏:
#include <iostream>
struct X {
X() { std::cout << "X"; }
};
struct Y {
Y(const X &x) { std::cout << "Y"; }
void f() { std::cout << "f"; }
};
int main() {
Y y {X{}};
y.f();
}
what exactly this line does
它创建一个临时 X
,通过调用默认构造函数对其进行值初始化,然后使用它来初始化一个 Y
变量,调用 const X&
转换构造函数。
where is connection to Most vexing parse
如果您尝试使用老式初始化语法来编写此代码
Y y (X());
那么所谓的"most vexing parse"会把this解释成一个函数,而不是一个变量,声明:一个叫做y
的函数,return类型为Y
和一个参数,其类型是(指向一个)函数 returning X
.
您可以添加额外的括号,这样它就不会被解释为函数声明:
Y y ((X()));
或者,自 C++11 起,您可以像您的示例那样使用大括号初始化。
Y y {X{}};
这很完美,它创建了一个对象 y
,将类型 X
的临时对象传递给构造函数。没有令人烦恼的解析(大多数或其他)。实际上,引入{}
的构造是为了解决很多情况下令人头疼的解析问题,例如:
Y y1();
Y y2(X());
两者都属于(最)令人烦恼的解析,因为它们都声明了函数,而不是对象。
但是,如果你使用称为 brace-initialization:
的大括号
Y y1{};
Y y2{X{}}; //as you've done yourself
然后都声明了对象,而不是预期的函数。
我对 Y y {X{}};
这行代码到底做了什么以及它与最令人烦恼的解析有什么联系感到困惑。一个简短的解释表示赞赏:
#include <iostream>
struct X {
X() { std::cout << "X"; }
};
struct Y {
Y(const X &x) { std::cout << "Y"; }
void f() { std::cout << "f"; }
};
int main() {
Y y {X{}};
y.f();
}
what exactly this line does
它创建一个临时 X
,通过调用默认构造函数对其进行值初始化,然后使用它来初始化一个 Y
变量,调用 const X&
转换构造函数。
where is connection to Most vexing parse
如果您尝试使用老式初始化语法来编写此代码
Y y (X());
那么所谓的"most vexing parse"会把this解释成一个函数,而不是一个变量,声明:一个叫做y
的函数,return类型为Y
和一个参数,其类型是(指向一个)函数 returning X
.
您可以添加额外的括号,这样它就不会被解释为函数声明:
Y y ((X()));
或者,自 C++11 起,您可以像您的示例那样使用大括号初始化。
Y y {X{}};
这很完美,它创建了一个对象 y
,将类型 X
的临时对象传递给构造函数。没有令人烦恼的解析(大多数或其他)。实际上,引入{}
的构造是为了解决很多情况下令人头疼的解析问题,例如:
Y y1();
Y y2(X());
两者都属于(最)令人烦恼的解析,因为它们都声明了函数,而不是对象。
但是,如果你使用称为 brace-initialization:
的大括号 Y y1{};
Y y2{X{}}; //as you've done yourself
然后都声明了对象,而不是预期的函数。