当我从赋值操作符返回值时,首先,调用复制构造函数的机制和基础是什么?

When I return by value from an assignment operator, firstly what is the mechanism and basis of calling the copy constructor?

本文关键字:机制 是什么 构造函数 调用 赋值操作符 返回值 首先 复制      更新时间:2023-10-16

考虑这段代码及其输出:

class test {    
    int a, b;
    public:
        test (int a, int b) : a(a), b(b) { cout << "Const" << endl;}
        test (const test & t) {
            cout << "Copy constructor" << endl;
            cout << "Being copied to = " << this << " from " <<  &t << endl;
            if (&t == this) {
                cout << "returning" << endl;
               return;
            }
            this->a = t.a;
            this->b = 6;//t.b;
        }
        test operator=(const test & in) {
        cout << "Assignment operator" << endl;
        this->a = in.a;
        this->b = in.b;
        cout << "Being written to = " << this << " from  "<< &in << endl;
        return *this;
    }
    test get () {
        test l = test (3, 3);
        cout << "Local return " << &l << endl;
        return l;
    }
    void display () {
        cout << a << " " << b << endl;
    }
};
int main () {
    int i = 5, &ref = i;
    test t(1,1), u(2,2);
    u = t.get();
    cout << "u address" << &u <<endl;
    //cout << "u ka = " << &u << endl;
    u.display();   
}
输出:

Const
Const
Const
Local return 0x7fff680e5ab0
Assignment operator
Being written to = 0x7fff680e5a90 from  0x7fff680e5ab0
Copy constructor
Being copied to = 0x7fff680e5a80 from 0x7fff680e5a90
u address0x7fff680e5a90
3 3

我知道从赋值返回的方式是通过引用,但我试图理解这是如何工作的,因为我是c++的初学者。地址0x7fff680e5a80是什么?这是从哪来的?哪个对象在调用复制构造函数?我希望u(地址0x7fff680e5a90)调用它

让我们遵循您的代码(我修改了您的构造函数来转储构造的this)。

首先是t和u。

Const at 0x7fffffffdeb0
Const at 0x7fffffffdea0

然后调用t.get,它初始化l.

Const at 0x7fffffffdec0

然后返回l。

Local return 0x7fffffffdec0

此处省略了通常会发生的复制构造函数。

Assignment operator from l to u
Being written to = 0x7fffffffdea0 from  0x7fffffffdec0

然后您返回值赋值(您应该通过引用返回),因此您从u复制到未存储的输出值(0x7fffffffde90 from u)

Copy constructor
Being copied to = 0x7fffffffde90 from 0x7fffffffdea0

然后打印u

u address0x7fffffffdea0

内t .

为了避免混淆(和不必要的复制),您应该在执行任何赋值操作符时通过引用返回:

test& operator=(const test & in);

您的赋值运算符不正确:

    test operator=(const test & in) {

你应该通过引用返回:

    test &operator=(const test & in) {

0x7fff680e5a80处的对象是test类型的右值临时对象,它从(不正确的)赋值操作符返回并立即丢弃:

test operator=(const test & in) {
    cout << "Assignment operator" << endl;
    this->a = in.a;
    this->b = in.b;
    cout << "Being written to = " << this << " from  "<< &in << endl;
    return *this;
}   //     ^-- copy constructor is called here

可以通过对赋值操作符的返回值进行右值引用来检查:

auto &&temp = (u = t.get());
std::cout << "Address of temp: " << &temp << std::endl;  // prints 0x7fffffffde90