I believe backwards compatibility plays a big part here. If the user defines any of the “Rule of three” functions (copy ctor, copy assignment op, dtor), it can be assumed the class does some internal resource management. Implicitly defining a move constructor could suddenly make the class invalid when compiled under C++11.
Consider this example:
class Res
{
int *data;
public:
Res() : data(new int) {}
Res(const Res &arg) : data(new int(*arg.data)) {}
~Res() { delete data; }
};
Now if a default move constructor was generated for this class, its invocation would lead to a double deletion of data
.
As for the move assignment operator preventing default move constructor definitions: if the move assignment operator does something other than default one, it would most likely be wrong to use the default move constructor. That’s just the “Rule of three”https://stackoverflow.com/”Rule of five” in effect.