【问题标题】:why isn't the copy constructor called [duplicate]为什么不叫复制构造函数[重复]
【发布时间】:2012-12-18 17:21:27
【问题描述】:

可能重复:
What are copy elision and return value optimization?

我很难理解为什么在下面的代码中没有调用复制构造函数。

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

谁能解释为什么只调用构造函数而没有复制构造函数?
谢谢。

【问题讨论】:

标签: c++


【解决方案1】:

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


标准参考

C++03 12.8.15:

[...] 这种复制操作的省略是 以下允许 情况(可以结合 消除多个副本):

[...]

  • 当临时类对象具有 未绑定到参考 (12.2) 将被复制到一个类对象 相同的 cv-unqualified 类型,副本 操作可以省略 构造临时对象 直接进入目标 省略副本

您可能会使用一些编译器设置来禁用此优化,例如在 gcc 的情况下,来自 man page

-fno-elide-constructor

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

但是,使用它会使您的代码无法跨不同的编译器移植。

【讨论】:

  • 难道还不够,即使用 gcc,将优化设置为 0 不进行优化吗?
  • @Stefan:我没试过,所以无法确认。
【解决方案2】:

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

请注意重要的一点,即使最终没有调用复制构造函数,在语义上要求可访问。也就是说,如果您创建复制构造函数private,您的代码将不会编译!!这是因为语义检查是在优化阶段之前完成的,这意味着编译器首先检查复制构造函数是否可访问; 如果它是可访问的,那么只会进入省略复制构造的优化阶段。

【讨论】:

  • 复制构造函数可访问的另一种推理方式是不保证复制省略。编译器可能会也可能不会执行此优化,因为标准并未强制要求它。因此,如果存在无法执行此优化的编译器,则它需要可访问复制构造函数。因此,由于标准不强制执行优化,它无法强制优化在没有复制构造函数的情况下工作。
  • @AlokSave:谢谢。又加了几句。
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-18
    • 2014-01-14
    • 1970-01-01
    • 2012-11-28
    • 2013-12-08
    • 2012-02-28
    • 1970-01-01
    相关资源
    最近更新 更多