#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 ());
}
参考message2
是message
返回的原始foo()
对象的最后所有者,对吧?
答案 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
将使用移动构造函数构造,因此它可能会蚕食message
中foo
分配的内存,但是如果std::move
可能会发生这种情况。使用{3}}然后短字符串的移动构造函数不会比复制构造函数更有效。
需要注意的另一件事是,在返回值时不必显式使用{{1}},返回值已知为r值引用。