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

什么时候允许编译器优化复制构造函数[复制]

聂迪
2023-03-14

今天我遇到了一些我不太理解的复制构造函数。

考虑下一个代码:

#include <iostream>
using namespace std;

class some_class {
  public:
    some_class() {

    }

    some_class(const some_class&) {
      cout << "copy!" << endl;
    }

    some_class call() {
      cout << "is called" << endl;
      return *this;  // <-- should call the copy constructor
    }
};

some_class create() {
  return some_class();
}

static some_class origin;
static some_class copy = origin; // <-- should call the copy constructor

int main(void)
{
  return 0;
}

然后在将原点分配给复制时调用复制构造函数,这是有意义的。但是,如果我将复制的声明更改为

static some_class copy = some_class();

它不叫。即使当我使用< code>create()函数时,它也不会调用复制构造函数。但是,当将其更改为

static some_class copy = some_class().call();

它确实调用了复制构造函数。一些研究解释说,允许编译器优化复制构造函数,这听起来是件好事。直到复制构造函数是非默认的,因为那时它可能会,也可能不会做一些明显的事情,对吗?那么什么时候允许编译器优化复制构造函数呢?

共有1个答案

唐渊
2023-03-14

由于 C 17,这种复制省略是有保证的,编译器不仅被允许,而且需要省略复制(或移动)构造,即使复制(或移动)构造函数具有可观察到的副作用。

在以下情况下,编译器需要省略类对象的复制和移动构造,即使 copy/move 构造函数和析构函数具有可观察到的副作用。对象被直接构造到存储中,否则它们将被复制/移动到存储中。复制/移动构造函数不必存在或可访问,因为语言规则确保不会发生复制/移动操作,即使在概念上也是如此:

> < li>

在变量的初始化中,当初始值设定项表达式是与变量类型相同的类类型(忽略cv限定)的prvalue时:

T x = T(T(T())); // only one call to default constructor of T, to initialize x

在返回语句中,当操作数是与函数返回类型相同的类类型(忽略cv限定)的prvalue时:

T f() {
    return T();
}

f(); // only one call to default constructor of T

您的代码片段与这两种情况完全匹配。

在C17之前,不需要编译器,但允许省略复制(或移动)构造,即使复制/移动构造函数有可观察到的副作用。请注意,这是一种优化,即使发生复制省略,复制(或移动)构造函数仍然必须存在且可访问。

另一方面,call()不匹配任何复制省略条件;它返回<code>*此

 类似资料:
  • 可能重复:< br >什么是复制省略和返回值优化? 我很难理解为什么在下面的代码中没有调用复制构造函数。 有人能解释一下为什么只调用构造函数,不调用复制构造函数吗?< br >谢谢。

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

  • 主要内容:默认拷贝构造函数拷贝和复制是一个意思,对应的英文单词都是 。 对于计算机来说,拷贝是指用一份原有的、已经存在的数据创建出一份新的数据,最终的结果是多了一份相同的数据。例如,将 Word 文档拷贝到U盘去复印店打印,将 D 盘的图片拷贝到桌面以方便浏览,将重要的文件上传到百度网盘以防止丢失等,都是「创建一份新数据」的意思。 在 C++ 中,拷贝并没有脱离它本来的含义,只是将这个含义进行了“特化”,是指用已经存在的对

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

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

  • 我有一个带有两个64位整数成员的结构X,以及一个构造函数: