简体   繁体   中英

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

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 move d 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM