在将匿名对象作为参数传递时,不会调用任何构造函数

时间:2017-08-18 13:33:37

标签: c++ c++11

#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 Constuctor作为参数时调用Move ConstructorBox()。但他们都没有被召唤。原因可能是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())时会发生什么?正在创造什么?

1 个答案:

答案 0 :(得分:15)

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

Box a(Box())

是名为a的函数的声明,它将Box (*)()类型的函数作为参数并返回Box

解决方案是使用(C ++ 11中的新内容)aggregate initialization构建对象:

Box a{Box{}}

demo

在此stackoverflow问题Most vexing parse: why doesn't A a(()); work?

中以最简单的形式讨论了MVP
  

如果你有一个表达式,那么它是有效的。例如:

((0));//compiles
     

要详细了解语言的定义方式以及编译器的工作原理,您应该了解Formal language theory或更具体的Context Free Grammars (CFG)以及有限状态机等相关资料。如果您对此感兴趣,虽然维基百科页面还不够,您将不得不拿到一本书。