I am trying to understand the move semantics are looking in to compiler generated move constructors (copy and assignment).
In Modern Effective C++, Scott Meyers says in Item #17 that if no explicit copy constructors are declared, the the compiler will generate move constructors, which will do member-wise move for non-static
members.
To confirm this, I am trying below code:
#include <iostream>
#include <string>
using namespace std;
class A
{
private:
std::string str;
public:
A() : str("Init string")
{
cout << "Default constructor" << endl;
}
A(std::string _str) : str(_str)
{
cout << "Constructor with string" << endl;
}
std::string getString()
{
return str;
}
};
int main() {
A obj1;
A obj2("Obj2 string");
cout << endl;
cout << "obj1: " << obj1.getString() << endl;
cout << "obj2: " << obj2.getString() << endl;
obj1 = std::move(obj2);
cout << endl;
cout << "obj1: " << obj1.getString() << endl;
cout << "obj2: " << obj2.getString() << endl;
return 0;
}
The output is:
Default constructor
Constructor with string
obj1: Init string
obj2: Obj2 string
obj1: Obj2 string
obj2: Obj2 string
But I expected it to be:
Default constructor
Constructor with string
obj1: Init string
obj2: Obj2 string
obj1: Obj2 string
obj2:
Because obj2.str would have been moved and now has an empty string.
What is the reason the compiler is not generating a move assignment constructor and invoking the copy assignment operator?
EDIT: Implementing the move assignment operator as below gives the expected output (i.e. empty string after calling std::move)
A& operator=(A&& obj)
{
cout << "Move assignment operator" << endl;
str = std::move(obj.str);
return *this;
}