2017-08-09 98 views
1

概念和實踐中,返回潛在取r值引用的函數的修改值的正確方法是什麼。函數中修正潛在的r值參考的正確返回值是多少?

template<class Vector> 
??? add_element(Vector&& v){ 
    v.emplace_back(1.); 
    return ???(v); 
} 

直覺告訴我這個,(因爲我做原始類型的不鬆動信息)

template<class Vector> 
Vector&& add_element(Vector&& v){ 
    v.emplace_back(1.); 
    return std::forward<Vector>(v); 
} 

但其他可能性之中是

template<class Vector> 
Vector& add_element(Vector&& v){ 
    v.emplace_back(1.); 
    return v; 
} 

甚至這些的,(基於此https://pizer.wordpress.com/2009/04/13/c0x-do-people-understand-rvalue-references/

template<class Vector> 
Vector // or typename std::decay<Vector>::type 
add_element(Vector&& v){ 
    v.emplace_back(1.); 
    return v; // or std::forward<Vector>(v); 
} 

什麼是最通用的方式來返回修改後的傳遞參數?

回答

5

在轉發引用的更一般情況下,返回的方式取決於您想要執行的操作。

幸運的是,在這種情況下,除一個之外的所有選擇都是錯誤的(危險的,脆弱的等),因此您可以輕鬆地返回容器。

template<class Vector> 
Vector add_element(Vector&& v){ 
    v.emplace_back(1.); 
    return std::forward<Vector>(v); 
} 

這就是我通常所做的。它可能需要一個臨時的,如果是的話,將臨時移動到返回值。

如果它需要一個非臨時的,它會修改它並返回相同類別的引用。

template<class Vector> 
Vector&& add_element(Vector&& v){ 
    v.emplace_back(1.); 
    return std::forward<Vector>(v); 
} 

這是一個不幸的想法。參考壽命延長不通過功能調用,所以

auto&& v = add_element(make_vector()); 

導致泄漏的參考。假設你的類型移動便宜(如向量),返回一個移入臨時副本是一個微不足道的成本,可以延長參考時間。

「但是」,你說,「我不使用auto&&」。那麼,對於容器,for(:),和參考懸垂。因此,通常,絕不會通過右值引用返回容器。

template<class Vector> 
Vector& add_element(Vector&& v){ 
    v.emplace_back(1.); 
    return v; 
} 

這兩個都丟失類型信息並防止參考壽命延長。

如果可以幫到你,永遠不要臨時退回&

時傳遞的左值這個奇怪的行爲:

template<class Vector> 
std::decay_t<Vector> add_element(Vector&& v){ 
    v.emplace_back(1.); 
    return std::forward<Vector>(v); 
} 

,因爲它既可以複製並修改其參數。我不確定你爲什麼想這樣做。

+0

如果我理解正確,即使參數不是容器,第一個選項就是這樣一種情況,它給出了必須不妥協的性能和一般性。沒有? – alfC

+0

@alfC如果移動物體昂貴,顯然它不是不妥協的表現。所有長度可變的'std'容器都很便宜,因此在這裏不適用。 – Yakk

+0

也是「永遠不會通過右值引用返回容器」:作爲反例,'std :: optional :: operator *()'或'std :: optional :: value()'_do_通過右值引用返回。 –