C++ 为什么要调用复制构造函数?
我有以下一段代码,其中有两件事最让我困扰:C++ 为什么要调用复制构造函数?,c++,c++11,C++,C++11,我有以下一段代码,其中有两件事最让我困扰: 原始构造函数调用发生在什么时间点? 在什么情况下调用复制构造函数? 构造函数和类的副本基本上在一个地方调用。 当你使用你的函数时,通过构造创建Samp,然后将其复制到void fnc void output(Samp s) 这就是问题所在。此函数按值传递对象。当你打电话的时候 o((char*)"Hello") ,它通过默认构造函数创建一个临时Samp对象,并通过复制构造函数创建另一个新对象以传递给函数。调用std::function的参数通过传递
构造函数和类的副本基本上在一个地方调用。 当你使用你的函数时,通过构造创建Samp,然后将其复制到void fnc
void output(Samp s)
这就是问题所在。此函数按值传递对象。当你打电话的时候
o((char*)"Hello")
,它通过默认构造函数创建一个临时Samp对象,并通过复制构造函数创建另一个新对象以传递给函数。调用
std::function
的参数通过传递给存储在std::function
对象中的可调用对象
因此,o(args…
的行为与输出(args…
不同。相反,它与:
output( std::forward<Args...>(args...) );
输出(std::forward(args…);
或者在这个具体的例子中
output( std::forward<Samp>( (char *)"Hello" ) );
输出(std::forward((char*)“Hello”);
在本例中,我们看到“完美”转发并不完美,因为此代码的行为与输出((char*)“Hello”)略有不同代码>
为forward
选择的重载的签名是Samp&&forward(Samp&&arg)代码>。因此,对于对std::forward
的函数调用,arg
必须绑定到一个临时物化的对象;这就是你看到的“构造器”
然后,“复制构造函数”是从std::forward
的返回值初始化输出
函数的参数。如果Samp
有一个move构造函数,那么这可能是一个move操作。为什么不一步一步地调试,看看哪个语句给出了哪个输出?我想你很难得到它,因为所有的输出都是由o((char*)“Hello”)
生成的。所以我建议您在使用printf的地方放置断点。然后一步一步地调试谢谢@Nitesh,我已经做了一些调查,结果表明,在堆栈帧被破坏后,确实在第38行调用了原始构造函数,然后执行返回到第38行,之后调用了“o”函数,但对象构造是由于调用了复制构造函数,这就是我想要得到的,是什么机制导致了这种情况发生原始构造函数调用正在将(char*)“Hello”
转换为Samp
。然后调用复制构造函数,因为第一个构造的对象是通过值复制到输出的。请注意,复制构造函数不会更改str
成员,因此打印它会生成Default
。然后,在控件到达main()
中的返回0
之前,这两个对象被销毁。根据编译器的使用年限,可能会出现省略临时变量的情况——但是,从您描述的输出来看,不会出现省略。太棒了!谢谢你,彼得,现在我明白了。最初,我认为输出((char*)“Hello”);和o((char*)“你好”);,因为直接调用“output”不会导致创建临时对象。谢谢!我已将“output”函数的签名更改为:void output(const Samp&s);它是有效的。您能否解释一下,为什么首先要创建这个临时对象?因为输出函数需要一个Samp对象,而不是char*,所以它通过Samp(char[])创建一个临时对象,我认为这不是一个好的答案,因为output((char*)“Hello”)代码>不创建任何临时文件。函数参数由char*
初始化,不涉及中间对象。答案应该解释输出((char*)“Hello”)代码>和o((char*)“Hello”)代码>。而且Samp类甚至没有默认构造函数,因此您的语句“it creates a temporary Samp object by default constructor”无法更正。我同意@M.M。理想情况下,函数签名将通过使用char[]的构造函数创建Samp对象。没有涉及副本。这个问题与std::function有关。
output( std::forward<Args...>(args...) );
output( std::forward<Samp>( (char *)"Hello" ) );