Search code examples
c++c++11move-semanticsrvalue-reference

Returning an rvalue - what is wrong with this code?


I came across the following code snippet

std::string&& test()
{
    std::string m="Hello";
    return (std::move(m));
}

int main()
{
     std::string&& m = test();
}

I understand the above code is incorrect and unsafe but I am not sure why. So far this is my understanding of the code. In the function test

  1. a local std::string variable called m is created on the stack.

  2. This string is then returned however instead of a copy being made its contents are moved to the temporary. At this point the function test ends calling the destructor of variable m (whose contents were moved to the temp)

  3. The temporary is now bound to the rvalue reference m. And from what I understand is that a temporary will remain alive until its binding object is alive and in scope .

Could someone please tell me where I might be going wrong ? Why is the code above unsafe ?


Solution

  • An rvalue reference is still a reference, your code is incorrect for the same reason as the function shown below

    std::string& test()
    {
        std::string m="Hello";
        return m;
    }
    

    In both cases, the function returns a reference to a local variable. std::move doesn't do anything other than cast m to string&&, so there is no temporary created that m in main then binds to. When test exits, the local variable is destroyed, and m is a dangling reference.

    To fix your code, change the return type from string&& to string.

    std::string test()
    {
        std::string m="Hello";
        return m;   // std::move is redundant, string will be moved automatically
    }
    
    int main()
    {
         std::string&& m = test();
    }
    

    Now the m in main can bind to the return value of test, and the lifetime of that is extended to match that of m.