【问题标题】:Most vexing parse [duplicate]最令人烦恼的解析[重复]
【发布时间】:2016-08-15 08:01:00
【问题描述】:

我在Cpp Quiz 看到了一个代码 [问题 #38]

#include <iostream>

struct Foo
{
  Foo(int d) : x(d) {}
  int x;
};

int main() 
{ 
  double x = 3.14;

  Foo f( int(x) );

  std::cout << f.x << std::endl;

  return 0;
} 

据说这段代码格式不正确,因为Foo f( int(x) ); 将被视为函数声明,而不是Foo 类型的对象声明。

据我所知,这是“最令人头疼的解析”的一个实例。我的问题是语句Foo f( int(x) ); 中的这种语法int(x) 是什么意思?到目前为止,我只看到如下函数声明:

  1. Foo f( int );

  2. Foo f( int x );

Foo f( int x );一样吗?

【问题讨论】:

    标签: c++ most-vexing-parse


    【解决方案1】:

    语句Foo f( int(x) );中的这个语法int(x)是什么意思?

    x 周围的括号是多余的,将被忽略。所以int(x)和这里的int x是一样的,表示一个名为x,类型为int的参数。

    Foo f( int x );一样吗?

    是的。 Foo f( int(x) );,是一个名为f的函数声明,返回Foo,接受一个名为x的参数,类型为int

    这是标准的解释。 [dcl.ambig.res]/1:

    (强调我的)

    由函数样式之间的相似性引起的歧义 cast 和 [stmt.ambig] 中提到的声明也可以出现在 声明的上下文。在这种情况下,选择是在一个 带有一组冗余括号的函数声明 参数名称和具有函数样式转换为的对象声明 初始化器。就像在 [stmt.ambig],决议是考虑任何可以 可能是一个声明

    注意:声明可以是 通过在参数周围添加括号来明确消除歧义。 可以通过使用复制初始化或 列表初始化语法,或使用非函数式强制转换。

    struct S {
      S(int);
    };
    
    void foo(double a) {
      S w(int(a));      // function declaration
      S x(int());       // function declaration
      S y((int(a)));    // object declaration
      S y((int)a);      // object declaration
      S z = int(a);     // object declaration
    }
    

    因此,int(x) 将被视为(参数的)声明而不是函数样式转换。

    【讨论】:

      【解决方案2】:

      问题是,由于我不知道的原因,将参数名称包装到原型中的括号中是有效的。所以

      Foo f(int(x));
      

      可以解释为

      Foo f(int x);
      

      认为是

      Foo f(int);
      

      然而,真正的问题是 C++ 作者,同样出于我不知道的原因,决定为几乎完全相同的语义(实例初始化)使用两种不同的语法形式是很酷的。

      这引入了一种语法歧义,可以通过说“如果某事物既可以是声明又可以是定义,那么它就是声明”来“解决”,从而触发陷阱。

      因此,C++ 解析器必须能够解析任意数量的标记,然后才能确定第一个标记的语义含义。

      除了编译器编写者之外,这显然不是什么大问题,但这意味着阅读 C++ 代码以理解它的人也必须能够做到这一点,而对于我们人类来说,这更难。从此“最头疼”。

      【讨论】:

      • 这是允许的,因为有时它是必需的——比如使int *a[10]int (*a)[10] 不同。并且没有人会在需要时将语法限制为 only
      • @BoPersson : 我在A confusing detail about the Most Vexing Parse 看到了代码,老实说我不明白:(.
      • @NeonGlow 规则是一样的,期望函数有两个参数,第二个是函数指针。
      • @songyuanyao:有道理。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-14
      • 2019-05-20
      • 1970-01-01
      相关资源
      最近更新 更多