Alvin Yang
Alvin Yang

Reputation: 3

Why is the move constructor/assignment called when setting an object equal to the return value of another function

#include <iostream>

class Box{
public:
int x;
Box(){
    x=0;
    std::cout << "Constructor" << std::endl;
}
Box(const Box& other){
    x = other.x;
    std::cout << "Copy constructor" << std::endl;
}
Box(Box&& other){
    x = other.x;
    other.x = 0;
    std::cout << "Move constructor" << std::endl;
}

Box& operator=(Box&& other) {
    x = other.x;
    other.x = 0;
    std::cout << "Move assignment" << std::endl;
    return *this;
}

Box& operator=(const Box &other){
    x = other.x;
    std::cout << "Copy assignment" << std::endl;
}

~Box(){
    std::cout << "Destructor" << std::endl;
    x=0;
}
};
Box send(Box b){
std::cout << "Sending" << std::endl;
return b;
}
int main(){
Box b1, b2;
b1 = send(b2);
return 0;
}   

In the output:

Constructor
Constructor
Copy Constructor
Sending
Move Constructor
Move Assignment
Destructor
Destructor
Destructor
Destructor

I'm not too sure why a move constructor then assignment was used when doing b1 = send(b2).

Upvotes: 0

Views: 80

Answers (2)

Dean Seo
Dean Seo

Reputation: 5693

Why is the move constructor/assignment called when setting an object equal to the return value of another function

Your send function returns b that is a parameter, not a local variable:

Box send(Box b) {
    std::cout << "Sending" << std::endl;
    return b; // b is a parameter
}

So there is no RVO optimization occuring, because returning a parameter disables RVO. Meanwhile, there's another optimization option available, an implicit std::move:

Box send(Box b) {
    std::cout << "Sending" << std::endl;
    return std::move(b); // implicit std::move is applied.
}

So it's constructed, using your move constructor:

Box(Box&& other);

You'll see no move construction if you create and return a local variable c instead:

Box send(Box b) {
    Box c;
    std::cout << "Sending" << std::endl;
    return c; // Returns c, not b -> No move construction thanks to RVO
}

because RVO then jumps in.

Upvotes: 1

molbdnilo
molbdnilo

Reputation: 66431

It's move-constructing the return value from the parameter b, then that return value is move-assigned to b1.

Upvotes: 1

Related Questions