2010-06-13 70 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值引用。