Consider the below move assignment operator:
class MyClass {
private:
ssize_t buf_size;
void* buf_ptr;
public:
MyClass &operator=(MyClass &&rhs) {
if (this != &rhs) {
buf_size = rhs.buf_size;
buf_ptr = rhs.buf_ptr;
rhs.buf_ptr = nullptr;
rhs.buf_size = -1;
}
return *this;
}
}
What prevents us from using &operator=(MyClass &&rhs) instead of &operator=(MyClass &rhs) as the method's signature? As far as I understand, all the references to rhs should just work if rhs is a lvalue.
I can see one issue: using &operator=(MyClass &rhs) makes copy assignment operator and move assignment operator looks identical and there is no way for us to identify which operator to call. But are there any deeper reasons?
There is no "deeper reason" for rvalue references than to be distinct from lvalue references. Automatically determining whether a reference is to an lvalue or an rvalue, and executing the correct code in response, is the entire reason for their existence. For instance,
myClass = MyClass{}won't work with a function taking an lvalue reference, because a temporary is not an lvalue.