为什么只有在返回* this时才调用Copy构造函数?

时间:2013-08-15 12:14:24

标签: 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()

现在输出

  

构造
  复制构造函数

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

现在如果我用

替换line(1)
Cents Add(int val){ Cents temp;return temp;}  // --->(2)

唯一的输出是

  

构造

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

2 个答案:

答案 0 :(得分:11)

这是一种称为 copy elision 的优化,有时也被称为“(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 Standard,12.8 / 31.

答案 1 :(得分:3)

这是因为大多数编译器执行Return Value Optimization(又称RVO)以节省复制。