#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 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())
时会发生什么?正在创造什么?
答案 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)以及有限状态机等相关资料。如果您对此感兴趣,虽然维基百科页面还不够,您将不得不拿到一本书。