If you don't pay attention to your money, others will. GreaterThanZero.com

Page 5 of: Rvalue References Explained, by Thomas Becker   about me

#### Is an Rvalue Reference an Rvalue?

 As before, let X be a class for which we have overloaded the copy constructor and copy assignment operator to implement move semantics. Now consider: ```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, that is, a reference which preferably and typically (although not necessarily!) refers to an rvalue. Therefore, it is quite plausible to expect that `x` itself should also bind like an rvalue, that is, ```X(X&& rhs); ``` should be called. In other words, one might expect that anything that is declared as an rvalue reference is itself an rvalue. 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.

 In the example above, the thing that is declared as an rvalue reference has a name, and therefore, it is an lvalue: ```void foo(X&& x) { X anotherX = x; // calls X(X const & rhs) } ``` Here is an example of something that is declared as an rvalue reference and does not have a name, and is therefore an rvalue: ```X&& goo(); X x = goo(); // calls X(X&& rhs) because the thing on // the right hand side has no name ``` And here's the rationale behind the design: 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. Hence the rule, "If it has a name, then it's an lvalue." So then what about the other part, "If it does not have a name, then it's an rvalue?" Looking at the `goo` example above, it is technically possible, though not very likely, that the expression `goo()` in the second line of the example refers to something that is still accessible after it has been moved from. But recall from the previous section: sometimes that's what we want! We want to be able to force move semantics on lvalues at our discretion, and it is precisely the rule, "If it does not have a name, then it's an rvalue" that allows us to achieve that in a controlled manner. That's how the function `std::move` works. Although it is still too early to show you the exact implementation, we just got a step closer to understanding `std::move`. It passes its argument right through by reference, doing nothing with it at all, and its result type is rvalue reference. So the expression ```std::move(x) ``` is declared as an rvalue reference and does not have a name. Hence, it is an rvalue. Thus, `std::move` "turns its argument into an rvalue even if it isn't," and it achieves that by "hiding the name." Here is an example that shows how important it is to be aware of the if-it-has-a-name rule. Suppose you have written a class `Base`, and you have implemented move semantics by overloading `Base`'s copy constructor and assignment operator: ```Base(Base const & rhs); // non-move semantics Base(Base&& rhs); // move semantics ``` Now you write a class `Derived` that is derived from `Base`. In order to assure that move semantics is applied to the `Base` part of your `Derived` objects, you must overload `Derived`'s copy constructor and assignment operator as well. Let's look at the copy constructor. The copy assignment operator is handled analogously. The version for lvalues is straightforward: ```Derived(Derived const & rhs) : Base(rhs) { // Derived-specific stuff } ``` The version for rvalues has a big fat subtlety. Here's what someone who is not aware of the if-it-has-a-name rule might have done: ```Derived(Derived&& rhs) : Base(rhs) // wrong: rhs is an lvalue { // Derived-specific stuff } ``` If we were to code it like that, the non-moving version of `Base`'s copy constructor would be called, because `rhs`, having a name, is an lvalue. What we want to be called is `Base`'s moving copy constructor, and the way to get that is to write ```Derived(Derived&& rhs) : Base(std::move(rhs)) // good, calls Base(Base&& rhs) { // Derived-specific stuff } ```