Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a move constructor need to use "rvalue reference"?

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...

like image 678
Oleksiy Avatar asked Mar 17 '26 14:03

Oleksiy


2 Answers

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 &&.

like image 197
Yakk - Adam Nevraumont Avatar answered Mar 20 '26 03:03

Yakk - Adam Nevraumont


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
like image 39
juanchopanza Avatar answered Mar 20 '26 03:03

juanchopanza



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!