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

None of the constructors are called on passing Anonymous Object as argument

本文关键字:调用 构造函数 任何 参数传递 对象      更新时间:2023-10-16
#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();
}

(演示(

在上面的代码中,我希望在将匿名对象Box()作为参数传递时调用Copy ConstuctorMove Constructor。但他们都没有被召唤。原因可能是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())时发生了什么?正在创建什么?

这是最令人烦恼的解析的情况。当某些东西可以解析为函数声明时,它就是。

Box a(Box())

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

解决方案是使用(C++11 中的新功能(聚合初始化来构造对象:

Box a{Box{}}

(演示(


在这个堆栈溢出问题中以最简单的形式讨论了 MVP 最令人烦恼的解析:为什么 A a((((; 工作?

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

((0));//compiles

要了解有关语言定义方式以及编译器如何工作的更多信息,您应该了解形式语言理论,或者更具体地说,上下文无关语法(CFG(和相关材料,如有限状态机。 如果你对此感兴趣,尽管维基百科页面还不够,但你必须买一本书。