为什么复制构造函数在C ++中调用语句d1 = d2 + d3?

时间:2013-01-24 07:15:14

标签: c++ copy-constructor

我是C ++的初学者,我正在使用的资源说明以下语句 d3 = d1 + d2; 会调用以下内容:

  • +运算符
  • 默认构造函数
  • 复制构造函数
  • 析构
  • 作业运算符
  • 析构

我不明白为什么在将结果分配给先前声明的变量时调用复制构造函数以及为什么调用2个构造函数。

运营商如下:

date& date::operator=(const date& other)
{
cout << "Date assignment op" << endl;
    if (this!=&other){
        day=other.day;
        month=other.month;
        year=other.year;
    }
    return *this;
}

date date::operator+(const date& other) const
{
    cout << "Date Operator + called" << endl;
    date temp;
    temp.day=day+other.day;
    temp.month=month+other.month;
    temp.year=year+other.year;
    return temp;
}

5 个答案:

答案 0 :(得分:8)

表达式(d1 + d2)在从operator +(return temp)返回时产生一个临时对象。从'temp'创建临时是通过复制构造函数完成的。然后将其分配给d3。

答案 1 :(得分:2)

当计算d1 + d2时,结果是临时对象。为了将一个对象分配给另一个对象,正在调用复制构造函数。

答案 2 :(得分:1)

默认情况下,return按值对象将从源对象复制构造一个临时对象,然后将该临时对象传递给调用者。换句话说,语句d3 = d1 + d2;基本上是这样做的:

date implicit_temp(operator+(d1, d2));
d3 = implicit_temp;

引入了以下逻辑:

// The + operator 
date temp; // The default constructor
temp.day = d1.day + d2.day;
temp.month = d1.month + d2.month;
temp.year = d1.year + d2.year;
// return temp;
date implicit_temp(temp); // The copy constructor
temp.~date(); // Destructor
// Assignment operator
d3.day = implicit_temp.day;
d3.month = implicit_temp.month;
d3.year = implicit_temp.year;
implicit_temp.~date(); // Destructor

它与您看到的输出顺序相同。

如果编译器支持RVO(返回值优化),则可以通过传递date隐藏参数来优化return语句创建的临时d3对象因此return可以通过temp运算符将d3变量直接分配给=,从而使代码行为就像它是这样写的:

void date::operator+(const date& other, date& result) const
{
    date temp;
    temp.day=day+other.day;
    temp.month=month+other.month;
    temp.year=year+other.year;
    result = temp;
}

这将在引擎盖下分解为这个逻辑:

// The + operator 
date temp; // The default constructor
temp.day = d1.day + d2.day;
temp.month = d1.month + d2.month;
temp.year = d1.year + d2.year;
// return temp; - Assignment operator
d3.day = temp.day;
d3.month = temp.month;
d3.year = temp.year;
temp.~date(); // Destructor

答案 3 :(得分:0)

在以下情况下调用

复制构造函数:

A a=b,
when you return an object,
when you pass an object.

你的+运算符重载函数返回一个临时对象。它实际上会调用一个拷贝构造函数。

答案 4 :(得分:0)

不要依赖

从技术上讲,您的operator+在其区块中有一个temp变量,必须将其传递到临时对象中,以便稍后将其提供给operator=

换句话说,operator=看作参数的内容不是temp operator+内的+,而是=的副本,其长度必须超过+阻止,让+发生。

如果有的话,如何:

  • {{1}}只有一个return语句(实际上有)
  • {{1}}返回的所有return语句总是只是一个同一个对象

编译器可以通过将临时局部变量与赋值中使用的临时变量合并来优化返回时复制,并完全省略副本。

这是极少数可以发生的优化之一,也可以消除副作用(参见C ++ 03的§12.8.15或C ++ 11的12.8.31)。

复制构造函数的调用与否最终取决于编译器所需的优化级别。

(感谢juanchopanza所有澄清)。