2010-06-13 36 views
3

Rvalues恕我直言,C++有很大的改进,但是一开始似乎相当不错。请看下面的代码:关于在C++中使用r值的问题0x

#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

高飞,你可以请选择托马斯提供的答案是正确的吗?看到标记为正确的错误答案是非常令人恼怒的。 – fredoverflow 2010-09-21 16:08:14

回答

9

不,这是不对的。在发现右值引用时,你会陷入通常的陷阱,就像Motti在接受的答案中一样! (我做了这个错误也是如此,在我先前与RREF测试)

如果你不想与RREF打交道时,拍你的脚,这种内在:

在大多数情况下,一个功能返回右值引用与返回正常引用的函数一样愚蠢。

因为右值引用是......引用!所以,如果你返回一个引用 - 不管是否为rvalue - 给“消息”,你返回一个对刚被销毁的对象的引用,因为它超出了范围,所以你返回一个悬而未决的引用。这是一个错误。另外,不要编写return std :: move(message),因为编译器已经知道“message”是一个临时的(右值),所以不需要用std :: move重写它。而实际上,编写return std :: move(东西)可以阻止优化。 (至少在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

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


你说得对,message2将使用移动构造函数,因此它可能蚕食通过messagefoo分配的内存来构建,但是这可能不是如果small string optimization则使用移动构造了会发生什么短字符串不会比复制构造函数更高效。

需要注意的另一件事是,您在返回值时不必明确使用std::move,因为返回值是r值引用。