tags:

views:

89

answers:

2

Rvalues IMHO are great improvement in C++, but at the beginning the're seems quite. Please look at code below:

#include <string>

std::string && foo (void)
{
    std::string message ("Hello!");

    return std::move (message);
}

void bar (const std::string &message2)
{
    if (message2 == "Bye Bye!")
        return;
}

int main ()
{
    bar (foo ());
}

Reference message2 is last owner of original message object returned by foo(), right?

+1  A: 

You're right, message2 will be constructed using the move constructor so it may cannibalize the memory allocated by message in foo, however this may not be what happens if the small string optimization is used then the move constructor for a short string will not be any more efficient than the copy constructor.

Another thing to note is that you don't have to explicitly use std::move when returning a value, return values are known to be r-value references.

Motti
+3  A: 

No, it's not right. You fell for the usual trap one make when discovering rvalue reference, as did Motti in the accepted answer ! (And I did this mistake too, in my earlier test with rref)

If you don't want to shoot you in the foot when dealing with rref, internalize this :

In most case, a function returning a rvalue references is as foolish as a function returning a normal reference.

Because rvalue references are... references ! So if you return a reference - rvalue or not - to "message", you return a reference to an object that was just destroyed, because it went out of scope, so you return a dangling reference. It's a bug.

Also, don't write return std::move(message) because the compiler know already that "message" is a temporary (a rvalue), so there is no need to recast it with std::move. And actually, writing return std::move(something) can prevent optimization. (at least on MSVC10 it seems to disable RVO)

So, the correct and most efficient way is :

#include <string>
std::string foo (void)
{
    std::string message ("Hello!");
    return message;
}

void bar (const std::string& message2)
{
    if (message2 == "Bye Bye!")
        return;
}

int main ()
{
    bar (foo());
}

Good old C++03 :)
Because NRVO kicks in and there is no copy, no move, only one construction.

Thomas Petit