C ++ 0x中的R值

时间:2010-06-13 19:59:15

标签: c++11

Rvalues恕我直言是C ++的重大改进,但最初看起来很混乱。请看下面的代码:

#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 ());
}

参考message2message返回的原始foo()对象的最后所有者,对吧?

2 个答案:

答案 0 :(得分:9)

不,这不对。当你发现rvalue参考时,你会陷入通常的陷阱,就像Motti在接受的答案中一样! (我在早期的rref测试中也犯了这个错误)

如果你不想在处理rref时用脚射击,请将其内化:

在大多数情况下,返回右值引用的函数与返回普通引用的函数一样愚蠢。

因为右值引用是......引用!因此,如果您将引用 - 是否为rvalue - 返回到message,则返回对刚刚销毁的对象的引用,因为它超出了范围,因此您返回一个悬空引用。这是一个错误。

另外,不要写return std::move(message),因为编译器已经知道message是临时值(rvalue),所以不需要用std :: move重新编写它。实际上,编写return std::move(something)可以阻止优化(至少在MSVC10上,它似乎禁用了RVO)。

因此,正确而有效的方法是:

#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());
}

好老C ++ 03 :)
因为NRVO开始并且没有副本,没有移动,只有一个构造。

答案 1 :(得分:1)

编辑:返回r值参考不是您想要做的事情。这个答案最初是在我还在掌握C ++ 11s r值引用的时候编写的。


你是对的,message2将使用移动构造函数构造,因此它可能会蚕食messagefoo分配的内存,但是如果std::move可能会发生这种情况。使用{3}}然后短字符串的移动构造函数不会比复制构造函数更有效。

需要注意的另一件事是,在返回值时不必显式使用{{1}},返回值已知为r值引用。