为什么在调用重载赋值运算符时调用复制构造函数?

why copy constructor is called at the time of calling overloaded assignment operator?

我正在尝试了解构造函数和赋值运算符的使用。我正在尝试使用下面的程序。

#include <iostream>
using namespace std;

class myclass {
    int x;
public:
    myclass (int p) {
        cout << "calling constructor" << endl;
        x = p;
    }
    myclass () {
        cout << "calling constructor with no arguments" << endl;
        x = 0;
    }
    myclass (myclass &t) {
        cout << "calling copy constructor" << endl;
        x = t.x;
    }

    myclass operator=(myclass &t) {
        cout << "calling assignment operator" << endl;
        x = t.x;
        return *this;
    }

    void show () {
        cout << "val = " << x << endl;
    }
};


int main() {
    myclass a1;
    a1.show();
    myclass a2 = a1;
    a2.show();
    myclass a3(a2);
    a3.show();
    myclass a4(200);
    a2 = a4;
    a2.show();
    return 0;
}

输出:

calling constructor with no arguments // call 1
val = 0
calling copy constructor // call 2
val = 0
calling copy constructor // call 3
val = 0
calling constructor // call 4
calling assignment operator // call 5
calling copy constructor // call 6 i am not able to understand this print line
val = 200

调用 1,是从 myclass a1 完成的;

调用 2,是从 myclass a2 = a1 完成的;

调用 3,是从 myclass a3(a2) 完成的;

调用 4,是从 myclass a4(200) 完成的;

调用 5,从 a2 = a4 完成;

但我无法得知调用 6 的来源,它是根据指令调用的:

a2 = a4;

但是,它如何调用复制构造函数?

任何 help/pointer 都会有很大的帮助。我正在从 c 进入 cpp,因此请多多包涵。

(你的复制构造函数和赋值运算符有点格式错误:它们应该将 const 引用作为参数,而赋值运算符应该 return 一个 引用 不是一个值)。

对于 myclass a2 = a1;a2 尚不存在。因此调用复制构造函数以使用 a1.

创建 a2

但是对于a2 = a4a2已经存在,所以赋值运算符用于赋值 a2a4 .

所以规则本质上是:如果对象不存在,则需要构造它。您观察到的输出可以通过应用此规则来解释。

改为

myclass& operator=(myclass &t)

然后:

calling constructor with no arguments
val = 0
calling copy constructor
val = 0
calling copy constructor
val = 0
calling constructor
calling assignment operator
val = 200

如果您 return 按值,将调用复制构造函数。 Return 通过引用避免调用复制构造函数。

 myclass operator=(myclass &t) {
    cout << "calling assignment operator" << endl;
    x = t.x;
    return *this;
}

上面的函数returns按值。 按值返回是调用复制构造函数的情况之一。 另外 AFAIK,这并不总是正确的(return 通过值调用复制构造函数),因为一些编译器实现了 return 值优化。

您的赋值运算符 returns 由 value,因此当它 returns.

时会生成另一个副本

这就是第六个电话的来源。

通常,赋值运算符 return 是 引用 ,因此当您 return *this 时,您实际上是 return *this:

myclass& operator=(myclass &t) {
//     ^