![](/img/trans.png)
[英]Should I use std::move or std::forward in move ctors/assignment operators?
[英]When should I use forward and move?
我有一個操作矢量的代碼:
template<typename T>
void doVector(vector<T>& v, T&& value) {
//....
v.push_back(value);
//...
}
對於普通的push_back
,我是否需要使用forward(value)
, move(value)
或者只是value
(根據新的C ++ 11)? 它們如何影響性能?
例如,
v.push_back(forward<T>(value));
當第二個參數是左值時,當前代碼將無法編譯,因為T&&
將變為X&
這意味着T
需要為X&
這意味着std::vector<T>
將成為std::vector<X&>
,這將不會匹配第一個參數是std::vector<X> &
。 因此,這是一個錯誤。
我會使用兩個模板參數:
template<typename T, typename V>
void doVector(vector<T> & v, V && value)
{
v.emplace_back(std::forward<V>(value));
}
由於V
可以是與T
不同的類型,因此emplace_back
更有意義,因為它不僅解決了問題,而且使代碼更通用。 :-)
現在是下一個改進:因為我們正在使用emplace_back
從參數value
創建類型T
的對象(可能使用構造函數),我們可以利用這個事實,並使其成為可變函數:
template<typename T, typename ...V>
void doVector(vector<T> & v, V && ... value)
{
v.emplace_back(std::forward<V>(value)...);
}
這更加通用,因為您可以將其用作:
struct point
{
point(int, int) {}
};
std::vector<point> pts;
doVector(pts, 1, 2);
std::vector<int> ints;
doVector(ints, 10);
希望有所幫助。
如果您需要完美的轉發含義,則使用forward(value)
,保留l值,r值等內容。
轉發非常有用,因為它可以幫助您避免為具有l-val,r-val和引用參數的不同組合的函數編寫多個重載
move(value)
實際上是一種將l值轉換為r值的轉換運算符
在性能方面,都避免制作額外的物品副本,這是主要的好處。
所以他們真的做了兩件事
當你說普通的push_back時,我不確定你的意思,這里有兩個簽名。
void push_back( const T& value );
void push_back( T&& value );
第一個你可以通過任何正常的l-val,但是對於第二個你必須“移動”一個l-val或向前一個r-val。 請記住,一旦移動l-val就無法使用它
這里的獎勵是一種資源 ,似乎可以很好地解釋r-val-refs的概念以及與之相關的其他概念。
正如其他人所建議你也可以切換到使用emplace,因為它實際上完美地將參數轉發給對象的構造函數,這意味着你可以隨意傳遞它。
std::forward
。 std::move
。 例如
template <typename T>
void funcA(T&& t) {
funcC(std::forward<T>(t)); // T is deduced and therefore T&& means forward-ref.
}
void funcB(Foo&& f) {
funcC(std::move(f)); // f is r-value, use move.
}
以下是Scott Meyers的一段精彩視頻,解釋了轉發引用(他稱之為通用引用 )以及何時使用完美轉發和/或std::move
:
C ++和2012年之后:Scott Meyers - C ++中的通用引用11
有關使用std::forward
更多信息,請參閱此相關問題: 使用forward的優點
那個視頻,IMO,有關何時使用std :: forward以及何時使用std :: move的最佳解釋。 它提出了通用參考的概念,這是IMO一個非常有用的推理移動語義的工具。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.