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

StackOverflow https://stackoverflow.com/questions/22564115

Вопрос

Consider this piece of code and its output:

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();   
}

Output:

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

I know the way to return from an assignment is by reference, but I was trying to understand how this works since I am a beginner to C++. What is the address 0x7fff680e5a80 ? Where is this coming from ? Which object is calling the copy constructor here ? I would expect u (address 0x7fff680e5a90) to call it.

Это было полезно?

Решение

Lets follow your code (I modified your constructor to dump the constructed this).

First you isntantiate t and u.

Const at 0x7fffffffdeb0
Const at 0x7fffffffdea0

Then you call t.get, which initializes l.

Const at 0x7fffffffdec0

You then return l.

Local return 0x7fffffffdec0

The copy constructor that would normally happen at this point is elided.

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

Then you are returning the assignment by value (you should return it by reference), so you copy from u to an output value that isn't stored (0x7fffffffde90 from u)

Copy constructor
Being copied to = 0x7fffffffde90 from 0x7fffffffdea0

And then you print u.

u address0x7fffffffdea0

Inside T.

To get rid of the confusing (and unessisary copy) you should return by reference when you do any assignment operator:

test& operator=(const test & in);

Другие советы

Your assignment operator is incorrect:

    test operator=(const test & in) {

You should return by reference:

    test &operator=(const test & in) {

The object at 0x7fff680e5a80 is a prvalue temporary object of type test that is returned from your (incorrect) assignment operator and immediately discarded:

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

You can check this by taking an rvalue reference to the return value of the assignment operator:

auto &&temp = (u = t.get());
std::cout << "Address of temp: " << &temp << std::endl;  // prints 0x7fffffffde90
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top