Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::move on a variable which already is T&&

Tags:

c++

c++11

On the page How to: Write a Move Constructor Microsoft has an example on how to write a move constructor. It is essentially of the form:

MyClass::MyClass(MyClass&& lhs)
{
    *this = std::move(lhs);
}

I have tried and std::move really is required here, but why? I thought the only thing move did was to convert to T&&. But lhs is already of type MyClass&&, is it not?

like image 464
Petter Avatar asked Jul 30 '13 14:07

Petter


People also ask

Can I use variable after std :: move?

You must not use a variable after calling std::move() on it.

What does std :: move () do?

std::move. std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object. In particular, std::move produces an xvalue expression that identifies its argument t . It is exactly equivalent to a static_cast to an rvalue reference type.

Can you return std :: move ()?

std::move is totally unnecessary when returning from a function, and really gets into the realm of you -- the programmer -- trying to babysit things that you should leave to the compiler.

What does move () do C++?

std::move() is a function used to convert an lvalue reference into the rvalue reference. Used to move the resources from a source object i.e. for efficient transfer of resources from one object to another. std::move() is defined in the <utility> header.


1 Answers

Named rvalue references are lvalues. Unnamed rvalue references are rvalues. This is important to understand why the std::move call is necessary in: foo&& r = foo(); foo f = std::move(r);

Take a look at this answer : https://stackoverflow.com/a/5481588/1394283 It explains it very well.


Take a look at this function :

void foo(X&& x)
{
  X anotherX = x;
  // ...
}

The interesting question is: which overload of X's copy constructor gets called in the body of foo? Here, x is a variable that is declared as an rvalue reference. Therefore, it is quite plausible to expect that x itself should also bind like an rvalue, that is, X(X&& rhs); should be called.

Allowing move sematics to be applied tacitly to something that has a name, as in

X anotherX = x;
// x is still in scope!

would be dangerously confusing and error-prone because the thing from which we just moved, that is, the thing that we just pilfered, is still accessible on subsequent lines of code. But the whole point of move semantics was to apply it only where it "doesn't matter," in the sense that the thing from which we move dies and goes away right after the moving.

That's why the designers of rvalue references have chosen a solution that is a bit more subtle than that:

Things that are declared as rvalue reference can be lvalues or rvalues. The distinguishing criterion is: if it has a name, then it is an lvalue. Otherwise, it is an rvalue.

Source : http://thbecker.net/articles/rvalue_references/section_05.html

like image 73
Pierre Fourgeaud Avatar answered Sep 27 '22 20:09

Pierre Fourgeaud