I am trying to get the grasp of rvalue references and move semantics with a simple self-made example but I can't understand a specific part. I have created the following class:
class A {
public:
A(int a) {
cout << "Def constructor" << endl;
}
A(const A& var) {
cout << "Copy constructor" << endl;
}
A(A&& var) {
cout << "Move constructor" << endl;
}
A& operator=(const A& var) {
cout << "Copy Assignment" << endl;
return *this;
}
A& operator=(A&& var) {
cout << "Move Assignment" << endl;
return *this;
}
};
I tried the following experiments to see if I can predict how the constructors/operators are going to be called:
- A a1(1) - The default constructor is going to be called. PREDICTED.
- A a2 = a1 - The copy constructor is going to be called. PREDICTED.
- a1 = a2 - The copy assignment operator is going to be called. PREDICTED.
Now, I created a simple function that just returns an A object.
A helper() {
return A(1);
}
- A a3 = helper() - The default constructor is going to be called in order to create the object that the helper returns. The move constructor is not going to be called due to RVO. PREDICTED.
- a3 = helper() - The default constructor is going to be called in order to create the object that the helper returns. Then, the move assignment operator is going to be called. PREDICTED.
Now comes the part I don't understand. I created another function that is completely pointless. It takes an A object by value and it just returns it.
A helper_alt(A a) {
return a;
}
- A a4 = helper_alt(a1) - This will call the copy constructor, to actually copy the object a1 in the function and then the move constructor. PREDICTED.
- a4 = helper_alt(a1) - This will call the copy constructor, to actually copy the object a1 in the function and then I thought that the move assignment operator is going to be called BUT as I saw, first, the move constructor is called and then the move assignment operator is called. HAVE NO IDEA.
Please, if any of what I said is wrong or you feel I might have not understood something, feel free to correct me.
My actual question: In the last case, why is the move constructor being called and then the move assignment operator, instead of just the move assignment operator?