Search code examples
c++11constructormovervalue-reference

C++11 , move constructor requiring to call std::move explicitely


Case 1 :I am writing a simple move constructor:

ReaderValue::ReaderValue(ReaderValue && other)
{
    moveAlloc(other);
}

The moveAlloc function prototype in the ReaderValue class is:

void moveAlloc(ReaderValue && other);

I get the error from gcc 4.8:

cannot bind 'ReaderValue' lvalue to 'ReaderValue&&'

So I need to call explicitely this in order to compile:

moveAlloc(std::move(other));

Case 2 : Now ReaderValue has a std::string stringData member

I make another constructor:

ReaderValue(std::string && otherString)
 : stringData(otherString)
{
}

This works, I do not need std::move to pass otherString to the stringData constructor

Question : What is the fundamental reason why I need to explicitely call std::move to pass the rvalue to a function in the first case? The error message says other is a lvalue, whereas it does look like a rvalue reference. Why not in the second case?

(Please don't reply about the actual implementation, or why do I need to do this, blah blah... That's only a fundamental language question)


Solution

  • ReaderValue::ReaderValue(ReaderValue && other)
    {
        //other here is a lvalue(has a name) referring to a rvalue
        //move alloc however takes a rvalue
        moveAlloc(other);
    }
    

    that is why you have to cast your lvalue to a rvalue explicitely

    moveAlloc(std::move(other)); //other now is a rvalue
    

    please note that all std::move does is effectively a cast to rvalue.

    In the second example with the string:

     ReaderValue(std::string && otherString)
     : stringData(otherString)
    { }
    

    calls

    std::string(const string& other);
    

    effectively copying the string, while:

    ReaderValue(std::string && otherString)
    : stringData(std::move(otherString))
    { }
    

    calls:

    std::string(string&& other);
    

    moving your string