2017-08-18 44 views
6
#include <iostream> 

struct Box 
{ 
    Box()   { std::cout << "constructor called" << std::endl; } 
    Box(const Box&) { std::cout << "Copy constructor called" << std::endl; } 
    Box(Box&&)  { std::cout << "Move constructor called" << std::endl; } 
    void run() const { std::cout << "Run" << std::endl;} 
}; 

int main() 
{ 
    Box a(Box()); 
    a.run(); 
} 

demo没有被称为在经过匿名对象作为参数

在上面的代码我期待任一Copy ConstuctorMove Constructor到在经过匿名对象Box()作为参数来调用。但是他们都没有被召唤。原因可能是copy elision。但是即使是构造函数也不会被要求匿名对象A()。实际上,上面的代码并没有编译和调用run()函数编译器给出了以下错误。

a.cpp: In function ‘int main()’: 
a.cpp:28:7: error: request for member ‘run’ in ‘a’, which is of non-class type ‘Box(Box (*)())’ 
    a.run(); 

因此,当我们输入Box a(Box())发生了什么?正在创建什么?

+3

你被MVP咬了。它认为'Box a(Box());'是一个名为'a'的函数声明,返回一个'Box'。 – Borgleader

+0

@YSC我不确定我是否同意你的格式 - 我更喜欢以前的版本。 – pingul

+1

@pingul较短的代码倾向于吸引更多的注意力,所以我的编辑没有(我希望)改变OP的原意。但它绝对是他们的回拨。 – YSC

回答

15

这是Most Vexing Parse的一种情况。当某些东西可以被解析为一个函数声明时,它就是。

Box a(Box()) 

是一个名为a采取Box (*)()类型的函数作为参数和返回Box函数的声明。

一种解决方案是使用(新中C++ 11),用于构建您的对象aggregate initialization

Box a{Box{}} 

demo


的MVP在其最简单的形式中所讨论这个计算器的问题Most vexing parse: why doesn't A a(()); work?

如果你确实有一个表达式已验证。例如:

((0));//compiles 

要了解更多关于语言是如何定义的,和编译器是如何工作的,你应该了解Formal language theory或者更具体Context Free Grammars (CFG)和相关材料,如有限状态机。如果你对此感兴趣,虽然维基百科页面不够用,但你必须得到一本书。