2017-04-18 25 views
-2

我有一個返回右值引用的函數。std :: vector :: push_back(T &&)在返回T &&的函數直接傳遞時創建T的默認構造值

auto function() -> int&& { 
    int x{10}; 
    std::cout << x << std::endl; // to check the value of x 
    return std::move(x); 
} 

現在,當我使用下面的代碼:

std::cout << function() << std::endl; 
std::vector<int> v; 
v.push_back(function()); 
std::cout << v[0] << std::endl; 

這將導致下面的輸出

10 
0 

看起來即使()函數返回一個右值引用,向量推回默認構造的int。

有趣的是,如果我有這樣的代碼:

auto x = function(); 
v.push_back(std::move(x)); 

這完美的作品。

看來,如果我只是從函數返回一個局部變量,那麼RVO無論如何都會做一個複製elision。但由於我正在做一個明確的std :: move()我絆倒RVO導致返回一個臨時變量。

現在,在v.push_back(function())中,我調用vector :: push_back(T & &)函數,結果是引用對temp變量的引用。在這種情況下,它總是趨向於0而不是垃圾(我猜測這是因爲優化開啓了)。但是,如果我嘗試捕獲函數的返回值,它可以工作,這大概是因爲在返回值過程中創建的臨時變量的值被複制到此局部變量。這看起來不像一個沒有定義的行爲的幸運兒。

回答

6

你的函數返回一個函數局部變量的引用,在任何人都可以使用它之前它被銷燬。 (使用右值引用與使用左值引用相同,這與使用右值引用一樣無效。)

+0

這有點混淆不清。當我使用類似'auto x = function()'的東西時,我可以看到x實際上保持了10的值,而不是默認構造的或垃圾。我預計,std :: move會傳遞本地對象的所有權,因此不會自動銷燬。 – abhijit

+1

不,「x」的生命週期以函數結束。如果它有時似乎有效,那只是未定義的行爲。 – aschepler

相關問題