当前位置: 首页 > 知识库问答 >
问题:

为什么复制构造函数没有被称为[复制]

商迪
2023-03-14

可能重复:< br >什么是复制省略和返回值优化?

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

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

有人能解释一下为什么只调用构造函数,不调用复制构造函数吗?< br >谢谢。

共有3个答案

蒲德曜
2023-03-14

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

我还没有检查过它,但你可能会编译你的代码优化,再次没有,看看汇编器代码。那么你也应该肯定地看到一些差异。

景安翔
2023-03-14

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

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

阳建弼
2023-03-14

这被称为复制省略。< br >编译器可以进行这种优化。尽管标准没有保证这一点,但是任何商业编译器都会尽可能地执行这种优化。

标准参考:

C 03 12.8.15:

[……]在以下情况下允许省略复制操作(可组合使用以消除多个复制):

[...]

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

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

-fno-elide-constructor

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

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

 类似资料:
  • 问题内容: Java为什么不支持C ++中的复制构造函数? 问题答案: Java。只是没有像在C ++中那样隐式地调用它们,我怀疑这是您的真正问题。 首先,复制构造函数无非是: 现在,C ++将使用以下语句隐式调用复制构造函数: 在这种情况下,克隆/复制在Java中根本没有意义,因为所有b1和b2都是引用,而不是像C 中那样的值对象。在C 中,该语句复制对象的状态。在Java中,它只是复制 引用

  • 问题内容: 如果不可变的类对象副本将与原始副本相等,那么为什么Java 中的类具有副本构造函数?这是一个错误还是背后有原因?在Java文档中,指定了: 问题答案: 复制字符串的主要原因是为了 “修剪行李” ,即仅将底层char数组修剪为必需的字符。 基本的char数组可能太大,因为通过调用创建字符串时,char数组可以在新的字符串实例和源字符串实例之间共享;偏移量指向第一个字符,并且包括长度。 我

  • 可能重复:< br >什么是复制省略和返回值优化? 我有以下程序: 我期望的输出如下: 但我得到以下信息: 问题是:为什么不将对象从func返回到main调用我的复制构造函数?

  • 在上面的代码中,执行以下语句时不调用复制构造函数: 既然返回是按值的,为什么不调用复制构造函数? 谢啦

  • 在C#中,当我创建一个空类时,它提供了一个默认的构造函数,但是当我提供一个带有参数的构造函数时,默认的构造函数不再被创建。 我的问题是: 为什么编译器不再给我默认的构造函数呢 这些问题来自于WCF,我需要默认构造函数,但也希望能够为构造函数提供值,并且不必每次都放置默认构造函数,而且我不认为未使用的默认构造函数会使很多开销。

  • 根据我的理解,当创建了临时对象时,将调用move构造函数。这里,函数返回一个临时对象,但我的程序没有打印来自移动构造函数的消息: