如何将返回对象的副本控制为新对象?

时间:2014-10-18 10:33:48

标签: c++ operator-overloading copy-constructor

在此代码中,operator =被重载以控制类A对象的操作符行为,并且还声明了复制构造函数以查看它是否用于复制过程。

我的问题是,如果输出中没有使用复制构造函数和赋值运算符,编译器使用什么来将a_object + b_object的返回对象复制到c_object?在这种情况下如何控制复制的行为?

#include <iostream>


#define PUTLINE(X)  std::cout<<X<<"----------------------------\n" ;

class A{
  int value ;
public:
  A(int v = 0) : value(v) {}

  A(const A & a) 
  { 
    std::cout << "copy constructor...\n" ; 
    value = a.value ;
  }
  const A & operator = (const A & a) {
    std::cout << " = operator... \n" ;
    this->value = a.value ;    
    return *this ;
  }

  const A operator + (const A & a) {
    return A(value + a.value) ;
  } 

  void print(std::ostream & os) {
    os << value  << std::endl ;
  }
};


int main () {
    A a_object(10); 
    A b_object(20);
    PUTLINE(1);
    A c_object = a_object + b_object ; // what does the compiler use to make this copy? 
    PUTLINE(2);
    A d_object = c_object;
    PUTLINE(3);
    c_object.print(std::cout);
    PUTLINE(4);
    d_object.print(std::cout);
    PUTLINE(5);
    a_object = c_object ;
    PUTLINE(6);
    a_object.print(std::cout);
}

输出看起来像这样:

1----------------------------
2----------------------------
copy constructor...
3----------------------------
30
4----------------------------
30
5----------------------------
 = operator... 
6----------------------------
30

2 个答案:

答案 0 :(得分:3)

您正在体验copy elisionreturn value optimisation (RVO)。在某些情况下,允许编译器直接在目标空间中构造返回的对象,从而避免创建临时对象并从中进行复制。

这正是您的案例中发生的事情:operator+的返回值是使用c_object构造函数直接在(int)空间构建的,所以你不要&# 39;看到对复制构造函数的调用。

使用GCC,您可以传递命令行标志-fno-elide-constructors,以防止复制省略。然后,您将看到所有复制构造函数调用。 Live example

答案 1 :(得分:0)

a_object + b_object是函数调用。返回值是分配给c_object的值。