A StackOverflow question asks why it is necessary to call std::move on a parameter when implementing a move constructor, given that the parameter is already declared T&&?
Named rvalue references are lvalues. Unnamed rvalue references are rvalues.
In other words, if you don’t explicitly move a into b X b = std::move(a);
then you haven’t declared that you’ve finished with a, which is a named variable – so the compiler will call X’s copy constructor instead of X’s move constructor.