20

Possible Duplicate:
What are copy elision and return value optimization?

I am having difficulty understanding why in the following piece of code the copy constructor is not called.

#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;
}

Can someone explain why only the constructor is called and no copy constructor ?
Thanks.

4

3 回答 3

25

这称为复制省略
允许编译器执行此优化。尽管标准不保证任何商业编译器都会尽可能执行此优化。


标准参考

C++03 12.8.15:

[...]在以下情况下允许省略复制操作(可以组合起来以消除多个副本):

[...]

  • 当尚未绑定到引用(12.2)的临时类对象将被复制到具有相同 cv-unqualified 类型的类对象时,可以通过将临时对象直接构造到省略副本的目标中来省略复制操作

您可以使用一些编译器设置来禁用此优化,例如在 gcc 的情况下,从手册页

-fno-elide-constructor

C++ 标准允许实现省略创建仅用于初始化相同类型的另一个对象的临时对象。指定此选项会禁用该优化,并强制 G++ 在所有情况下调用复制构造函数。

但是,使用它会使您的代码在不同的编译器之间不可移植。

于 2013-01-04T09:22:47.053 回答
11

这是因为您的编译器执行了优化。允许编译器执行此类优化,尽管这不是必需的,因此不能保证。

请注意重要的一点,即使最终没有调用复制构造函数,它在语义上也是可访问的。也就是说,如果您制作了 copy-constructor private,您的代码将无法编译!这是因为语义检查是在优化阶段之前完成的,这意味着编译器首先检查复制构造函数是否可访问;如果它是可访问的,那么只有在复制构造被忽略的优化阶段才会到来。

于 2013-01-04T09:22:59.857 回答
0

正如其他人已经很好地提到的那样,这是因为您的编译器进行了优化。

我还没有检查它,但您可能可以通过优化编译您的代码,然后再不查看汇编代码。那么你也应该明确地看到一些差异。

于 2013-01-04T09:41:44.880 回答