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/