【问题标题】:Function definition or variable definition?函数定义还是变量定义?
【发布时间】:2014-12-11 13:00:06
【问题描述】:

为什么编译器将此行解释为函数定义而不是变量定义:

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

VS2010 在“y.f();”行出现以下错误

left of '.f' must have class/struct/union

标准的哪一部分描述了这种行为? 以下问题的答案没有提供有关它的详细信息: Most vexing parse

【问题讨论】:

  • 顺便说一句,这不是编译器错误。这是最令人头疼的解析问题,巧妙地伪装。
  • 根据编辑投票重新打开 - 来自标准的引用实际上是有用的。 6.8 讨论了表达式语句与声明的歧义,但最令人头疼的解析实际上是两个声明之间的歧义。

标签: c++ language-lawyer most-vexing-parse


【解决方案1】:

考虑一下:

float foo( int () )

这声明了一个函数foo(接受一个返回int的函数)返回float

现在阅读

Y y(X());

as y as function(接受返回X的函数)返回Y

问题的出现是由于C++ most vexing parse

可以解决:

 Y y{ X() }; // requires C++11

Y y( ( X() ) );
  // ^     ^ notice parenthesis 

更新基于编辑:

来自标准的引述

§ 8.2 歧义分辨率 [dcl.ambig.res]

1 - 由于函数样式转换和 6.8 中提到的声明之间的相似性而产生的歧义也可能出现在声明的上下文中。 在这种情况下,选择是在参数名称周围带有一组冗余括号的函数声明和以函数样式强制转换作为初始值设定项的对象声明之间进行选择。正如6.8 中提到的歧义一样,解决方案是将任何可能是声明的构造视为声明。 [注意:声明可以通过非函数样式强制转换明确地消除歧义,通过 a =指示初始化或删除参数名称周围的多余括号。 ]

[Example:

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 z = int(a); // object declaration
}
—end example]

以下类似的其他示例。

【讨论】:

  • Y y = X(); 不等同于Y y{ X() };。 C++03 中的正确解决方案是Y y( (X()) );
  • 但是在某些情况下Y y = X(); 会按预期工作并且更具可读性。
【解决方案2】:

Most vexing parse problemY y(X()) 实际上是名为 y 的函数声明,它返回 Y 并接收函数类型的参数,返回 X 并且什么也不接收。

在 C++11 中使用 {} 构造对象解决了这个问题。

【讨论】:

    猜你喜欢
    • 2021-10-23
    • 2011-02-08
    • 2014-05-25
    • 2017-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多