Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C++11 have implicit moves for value parameters, but not for rvalue parameters?

Tags:

In C++11, value parameters (and other values) enjoy implicit move when returned:

A func(A a) {     return a; // uses A::A(A&&) if it exists } 

At least in MSVC 2010, rvalue reference parameters need std::move:

A func(A && a) {     return a; // uses A::A(A const&) even if A::A(A&&) exists } 

I would imagine that inside functions, an rvalue reference and a value behave similar, with the only difference that in case of values, the function itself is responsible for destruction, while for rvalue references, the responsibility is outside.

What is the motivation for treating them differently in the standard?

like image 267
Arno Avatar asked Mar 19 '12 22:03

Arno


People also ask

What is c++ 11 move semantics?

In C++11, the answer is--you can! That's what rvalue references and move semantics are for! Move semantics allows you to avoid unnecessary copies when working with temporary objects that are about to evaporate, and whose resources can safely be taken from that temporary object and used by another.

What is a semantic move?

Move semantics is about transferring resources rather than copying them when nobody needs the source value anymore. In C++03, objects are often copied, only to be destroyed or assigned-over before any code uses the value again.

What is rvalue reference in c++?

Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.


2 Answers

The standardization committee expended great effort in creating wording so that moves would only ever happen in exactly two circumstances:

  1. When it is clearly safe to do so.
  2. When the user explicitly asks (via std::move or a similar cast).

A value parameter will unquestionably be destroyed at the end of the function. Therefore, returning it by move is clearly safe; it can't be touched by other code after the return (not unless you're deliberately trying to break things, in which case you probably triggered undefined behavior). Therefore, it can be moved from in the return.

A && variable could be referring to a temporary. But it could be referring to an lvalue (a named variable). It is therefore not clearly safe to move from it; the original variable could be lurking around. And since you didn't explicitly ask to move from it (ie: you didn't call std::move in this function), no movement can take place.

The only time a && variable will be implicitly moved from (ie: without std::move) is when you return it. std::move<T> returns a T&&. It is legal for that return value to invoke the move constructor, because it is a return value.

Now it is very difficult to call A func(A &&a) with an lvalue without calling std::move (or an equivalent cast). So technically, it should be fine for parameters of && type to be implicitly moved from. But the standards committee wanted moves to be explicit for && types, just to make sure that movement didn't implicitly happen within the scope of this function. That is, it can't use outside-of-function knowledge about where the && comes from.

In general, you should only take parameters by && in two cases: either you're writing a move constructor (or move assignment operator, but even that can be done by value), or you're writing a forwarding function. There may be a few other cases, but you shouldn't take && to a type unless you have something special in mind. If A is a moveable type, then just take it by value.

like image 81
Nicol Bolas Avatar answered Oct 21 '22 04:10

Nicol Bolas


This was fixed for C++20 by P0527 and P1825. The only way to have a function parameter bind to an rvalue reference is for the source to either be a temporary or for the caller to explicitly cast a non-temporary to an rvalue (for instance, with std::move). Therefore, this "mandatory optimization" was deemed safe.

like image 40
David Stone Avatar answered Oct 21 '22 03:10

David Stone