For example, the following move constructor works without the && (rvalue reference):
Obj::Obj(Obj& obj) : elem { obj.elem }, data(obj.data) {
obj.elem = nullptr;
obj.data = 0;
}
I don't really understand why it's necessary...
Rvalue reference arguments will refuse to bind to non-rvalue references. Because of this restriction, move operations will only happen when the object being moved from can never be explicitly referred to in code at a later time (because it is a temporary being discarded, or a local variable being returned), or because the caller explicitly moved from them.
To see why this is required, you could look up the history of auto_ptr, or you could read this example, which uses your Obj type:
int main() {
Obj a;
Obj b = a; // oops! You just *moved* a into b!
}
with a proper move constructor, it is only called when the right hand side is a value that is going to be immediately discarded in a way that the compiler can detect, or you call move.
On top of that, & references refuse to bind to temporaries -- a temporary can only bind to a const& or a &&.
Your example cannot bind to a temporary, so these would not work:
Obj makeObj() { return Obj(); }
Obj o1(Obj()); // Error
Obj o2(makeObj()); // Error
Furthermore, it makes it very easy to break things, because you essentially have a copy constructor that steals state away from the object it is copying from:
Obj o1;
Obj o2{o1}; // o1 is modified
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With