复制操作完成后无效的对象?

时间:2012-07-26 11:09:22

标签: c++ most-vexing-parse

  

可能重复:
  Why is it an error to use an empty set of brackets to call a constructor with no arguments?
  Most vexing parse: why doesn't A a(()); work?

这个让我发疯。也许它太简单了。

struct Foo
{
  Foo() {}
  Foo(const Foo& f) {}
  void work() {}
};

int main()
{
  Foo f( Foo() );
  f.work();
}

GCC 4.6给了我:

error: request for member ‘work’ in ‘f’, which is of non-class type ‘Foo(Foo (*)())’

在省略复制操作后,有效代码可能如下所示:

int main()
{
  Foo f;
  f.work();
}

但为什么我不能打电话给work() ??

编辑:

是的,重复(见下文)。在搜索时没有找到原始帖子,因为这个症状的来源位于我没想到的地方。

4 个答案:

答案 0 :(得分:3)

因为Foo f( Foo() );是函数声明。

我想你想要:Foo f;

或者如果你想复制构造:

Foo f( (Foo()) );

答案 1 :(得分:1)

f实际上是main函数中的函数声明。 试试

Foo f((Foo())); // to make the definition of f explicit enough.

答案 2 :(得分:1)

n3337 8.2

  

功能风格之间相似性产生的模糊性   在6.8中提到的演员和声明也可以在上下文中出现   声明。在这种情况下,选择是在一个函数之间   声明与参数周围的一组冗余括号   具有函数样式转换的名称和对象声明   初始化。正如6.8中提到的含糊不清一样   解决方案是考虑任何可能是a的构造   声明声明。 [注意:声明可以明确   由非函数式转换消除歧义,由=表示   初始化或删除周围的冗余括号   参数名称。 - 尾注] [例子:

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
}
  

- 结束示例]

答案 3 :(得分:1)

C ++解析器将Foo f(Foo());表达式解释为具有签名Foo(Foo(*)())的函数声明,即返回Foo的函数并将函数指针指向返回Foo的函数。在参数周围添加显式括号,如Foo f((Foo()));,将解决歧义。但实际上只考虑Foo f;来避免冗余代码。