c++ - 为什么仅当我们返回 *this 时才调用 Copy 构造函数?

标签 c++

Class Cents(){  
 int m_val;  
 public:  
  Cents(int x=0){ cout<<"Constructor";}
  Cents(const Cents& src){ cout<<"Copy constructor"}
  Cents Add(int val){m_val=val; return *this}  // --->(1)
 }  

假设我有 Cents object obj 并且正在调用 obj.Add()

现在输出将是

Constructor
Copy constructor

所以我的假设是 Here 通过在 (1) 中返回 *this 我们将 *this 对象值复制到一个新的临时 Cents 对象。这就是复制构造函数被调用的原因。

现在,如果我将第 (1) 行替换为

Cents Add(int val){ Cents temp;return temp;}  // --->(2)

唯一的输出是

Constructor

为什么没有调用复制构造函数?我对第 (1) 行的假设是错误的吗?

最佳答案

这是一种称为复制省略的优化,有时被喜欢缩写词的人称为“(N)RVO”(“(命名)返回值优化”)。

在某些情况下,当一个对象(概念上)在一个地方创建,复制或移动到另一个地方,然后销毁时,程序被允许在它的最终位置创建它。即使省略的构造函数和/或析构函数有副作用,也允许这种优化,就像它们在您的示例中所做的那样。

从函数返回临时变量或局部变量就是其中一种情况。不是在函数的堆栈帧中创建 temp 然后将其复制到调用者的,而是程序可以直接在调用者的帧中创建它。

当您返回*this 时,无法删除拷贝,因为*this 的生命周期超出了函数的范围。从调用者的角度来看,将有两个对象,因此程序必须实际进行复制:

Cents original;
Cents copy = original.Add(42);

// "copy" and "original" both exist: the object must have been copied.

有关此优化可以省略哪些操作的完整详细信息,请参阅 C++11 标准,12.8/31。

关于c++ - 为什么仅当我们返回 *this 时才调用 Copy 构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18252679/

相关文章:

c++ - 如何在一个函数中访问另一个函数中的变量?

c++ - 堆栈损坏,不知道是什么原因造成的

c++ - 无序集删除/插入循环

c++ - 如何安全地比较两个无符号整数计数器?

c++ - OpenGL 和 GLM : How to send a matrices array to GLSL

c++ - 视锥体和透视矩阵

c++ - 从char数组中删除字符时出现问题

c++ - '非静态引用成员,不能使用默认赋值运算符'

c++ - IBM MQ mqrc 2042

c++ - QDialog 不会自动缩小以适应它的内容