Search code examples
c++movesemantics

How rvalue parameter works?


So I just got really surprised to find that in this code:

void AddLayer( shared_Layer_ptr && pNewLayer_p ){

        m_layers.push_back( pNewLayer_p ); // *
    }

The push_back being called is the "& param", not the "&& param" version. m_layers is a std::vector. Since pNewLayer_p is a "&&", I though it was a damn rvalue..The only way I manage to get the push_back("&& param") called is by using std::move:

m_layers.push_back( std::move(pNewLayer_p) );

To me seems redundant since pNewLayer_p is already a "&&".. Im sure missing something, what is it?


Solution

  • pNewLayer_p is an rvalue reference, but it is not an rvalue itself – basically because it has a name. Rvalues are defined as follows in the Standard:

    (3.10/1) An rvalue (so called, historically, because rvalues could appear on the right-hand side of an assignment expression) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associated with an object.

    In other words, rvalues are literals, temporaries and otherwise unnamed objects (such as xvalues, i.e. values that have just been returned by a function, but not been assigned to anything yet).

    The rvalue reference pNewLayer_p in your code is a named object, so it is itself an lvalue. Applying std::move to it, which is formally a function, turns it (formally) into something returned from a function, i.e. an xvalue, which is an rvalue that you can pass to the move-version of push_back. This is what std::move exists for.

    (Note: The above assumes that shared_Layer_ptr is a type, not a template parameter. If it is a template parameter, shared_Layer_ptr && would be a so-called universal reference, i.e. it may be an lvalue reference or an rvalue reference depending on how the template is instantiated. In this case, std::forward would be the appropriate function to use instead of std::move.)