【问题标题】:Most vexing parse C++11最令人头疼的解析 C++11
【发布时间】:2015-05-30 10:58:02
【问题描述】:

我对@9​​87654321@ 这行到底做了什么以及它与最令人烦恼的解析有何联系感到困惑。一个简短的解释表示赞赏:

#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();
}

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    这条线的作用

    它创建一个临时的X,通过调用默认构造函数对其进行值初始化,然后使用它来初始化一个Y变量,调用const X&amp;转换构造函数。

    最麻烦的解析的连接在哪里

    如果您尝试使用老式初始化语法来编写此代码

    Y y (X());
    

    那么所谓的“最令人头疼的解析”会将其解释为一个函数,而不是一个变量,声明:一个名为 y 的函数,返回类型为 Y 和一个参数,其类型为 (指向 a) 函数的指针返回 X

    您可以添加额外的括号,使其不能被解释为函数声明:

    Y y ((X()));
    

    或者,从 C++11 开始,您可以像示例一样使用大括号初始化。

    【讨论】:

    • sometype a(()) 这给出了 C++14 上的 Error: Expected Expression(在内括号内)。 sometype 是一个类。
    【解决方案2】:
    Y y {X{}};
    

    这是完美的,它创建了一个对象y,将X 类型的临时对象传递给构造函数。没有令人烦恼的解析(大多数或其他)。其实很多时候引入{}的构造是为了解决令人头疼的解析问题,比如这些:

     Y y1();
     Y y2(X());
    

    两者都属于(大多数)令人烦恼的解析,因为它们都声明了函数,而不是对象。

    但是,如果您使用称为 brace-initialization 的花括号:

     Y y1{};
     Y y2{X{}}; //as you've done yourself
    

    然后两者都像预期的那样声明对象,而不是函数。

    【讨论】:

    • Y y2(X())Y y2(X x1) 都被解释为函数,但A a1(2) 被解释为声明,其中Class A 包含1-arg constructor,它采用int 类型参数。这两件事不是矛盾的吗?
    • 也将Y y2(X{}) 解释为变量声明。我没有清楚地理解这个概念。
    • @AbhishekMane:请阅读更多相关信息。那里有足够的内容。我相信如果你阅读更多,你会明白的。 为什么 A a(int()) 被视为函数,但 A a(0) 不是...的一个非常简短的解释是:如果语法 可以 被解释为函数和对象both,然后规范说它应该被符合标准的编译器解释为函数。
    猜你喜欢
    • 2020-08-17
    • 2013-06-08
    • 1970-01-01
    • 2018-05-26
    • 2019-11-30
    • 2013-08-02
    • 2018-07-21
    • 1970-01-01
    相关资源
    最近更新 更多