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

时间:2016-05-18 11:16:05

标签: c++ copy-constructor

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

#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;

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

任何帮助/指针都将是一个很好的帮助。我从c潜入cpp,所以请耐心等待。

4 个答案:

答案 0 :(得分:2)

(复制构造函数和赋值运算符稍有不正确:它们应该使用const引用作为参数,赋值运算符应该返回引用而不是值)。

使用myclass a2 = a1;a2尚不存在。因此,使用a2调用复制构造函数来创建a1

但是a2 = a4 a2已经存在,因此赋值运算符用于 a2分配给a4

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

将其更改为

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

如果按值返回,将调用复制ctor。 通过引用返回以避免调用copy ctor。

答案 3 :(得分:1)

您的赋值运算符按返回,因此返回时会生成另一个副本。

第六次来电的来源。

通常情况下,赋值运算符会返回引用,因此当您return *this时,确实会返回*this

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