我很难理解为什么在下面的代码中没有调用复制构造函数。
#include <iostream>
class Test
{
public:
Test(int){std::cout << "Test()" << std::endl;}
Test(const Test&){std::cout << "Test(const Test&)" << std::endl;}
};
int main()
{
// Test test;
Test test2(Test(3));
return 0;
}
有人可以解释为什么只调用构造函数而没有复制构造函数吗? 感谢。
答案 0 :(得分:24)
这称为 copy elision 允许编译器进行此优化。虽然标准无法保证,但任何商业编译器都会尽可能地执行此优化。
标准参考:
C ++ 03 12.8.15:
[...]复制操作的省略是 允许以下内容 情况(可以合并 消除多份副本):
[...]
- 当一个临时类对象有 没有受到参考(12.2) 将被复制到一个类对象 相同的cv-unqualified类型,副本 操作可以省略 构造临时对象 直接进入了目标 省略副本
您可以使用一些编译器设置来禁用此优化,例如gcc,来自 man page :
-fno-elide-constructor
C ++标准允许实现省略创建临时文件,该临时文件仅用于初始化相同类型的另一个对象。指定此选项会禁用该优化,并且 迫使G ++在所有情况下调用复制构造函数。
但是,使用它会使您的代码在不同的编译器中不可移植。
答案 1 :(得分:11)
这是因为您的编译器执行了优化。编译器允许执行此类优化,但它不是要求,因此不保证。
请注意,尽管最终未调用复制构造函数,但语义上 可访问。也就是说,如果你创建了复制构造函数private
,你的代码将不编译!!这是因为语义检查在优化阶段之前完成,这意味着编译器首先检查复制构造函数是否可访问; 如果 可访问,那么只会出现复制构造被省略的优化阶段。
答案 2 :(得分:0)
正如其他人已经提到的那样,这是因为编译器的优化。
我还没有检查过它,但是您可能可以使用优化编译代码,而不需要查看汇编程序代码。那么你也应该定义一些差异。