You invested your money. Find out what happened.
GreaterThanZero.com


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

The Case of the Implicit Move

At one point during the (often complex and controversial) discussion of rvalue references, the Standard Committee decided that move constructors and move assignment operators, that is, rvalue reference overloads for copy constructors and copy assignment operators, should be generated by the compiler when not provided by the user. This seems like a natural and plausible thing to request, considering that the compiler has always done the exact same thing for ordinary copy constructors and copy assignment operators. In August of 2010, Scott Meyers posted a message on comp.lang.c++ in which he explained how compiler-generated move constructors can break existing code in a rather serious way.

The committee then decided that this was indeed cause for alarm, and it restricted the automatic generation of move constructors and move assignment operators in such a way that it is much less likely, though not impossible, for existing code to break. The final state of affairs is described in detail in Item 17 of Scott Meyers' book “Effective Modern C++.”

The issue of implicitly moving remained controversial all the way up to the finalization of the Standard (see e.g. this paper by Dave Abrahams). In an ironic twist of fate, the only reason why the committee considered implicit move in the first place was as an attempt to resolve the issue with rvalue references and exceptions as mentioned in Section 9. This problem was subsequently solved in a more satisfactory way via the new noexcept keyword. Had the noexcept solution been found just a few months earlier, implicit move may have never seen the light of day. Oh well, so it goes.

Ok, that's it, the whole story on rvalue references. As you can see, the benefits are considerable. The details are gory. As a C++ professional, you will have to understand these details. Otherwise, you have given up on fully understanding the central tool of your trade. You can take solace, though, in the thought that in your day-to-day programming, you will only have to remember three things about rvalue references:

  1. By overloading a function like this:
    void foo(X& x); // lvalue reference overload
    void foo(X&& x); // rvalue reference overload
    
    you can branch at compile time on the condition "is foo being called on an lvalue or an rvalue?" The primary (and for all practical purposes, the only) application of that is to overload the copy constructor and copy assignment operator of a class for the sake of implementing move semantics. If and when you do that, make sure to pay attention to exception handling, and use the new noexcept keyword as much as you can.
     
  2. std::move turns its argument into an rvalue.
     
  3. std::forward allows you to achieve perfect forwarding if you use it exactly as shown in the factory function example in Section 8.
Enjoy!