關於std::move和std::forward
阿新 • • 發佈:2019-02-03
這篇文章介紹的真不錯:http://www.cnblogs.com/catch/p/3507883.html
總結起來:
1. std::move是將左值變成右值減少不必要的拷貝;
2. std::forward保持一個值的左值和右值特性不變,以變傳給既能接受左值又能接受右值的函式,例:
template<class TYPE, class ARG>
TYPE* acquire_obj(ARG&& arg)
{
return new TYPE(forward<ARG>(arg));
}
3. 本質上,std::move和std::forward底層實現都是呼叫static_cast來進行型別轉換的。所以在執行期間不會有任何額外的消耗。
4.
在引數型別推導上,c++11 加入瞭如下兩個原則: 原則 (1): 引用摺疊原則 (reference collapsing rule),注意,以下條目中的 T 為具體型別,不是推導型別。 1) T& & (引用的引用) 被轉化成 T&. 2)T&& & (rvalue的引用)被傳化成 T&. 3) T& && (引用作rvalue) 被轉化成 T&. 4) T&& && 被轉化成 T&&. 原則 (2): 對於以 rvalue reference 作為引數的模板函式,它的引數推導也有一個特殊的原則,假設函式原型為: template<class TYPE, class ARG> TYPE* acquire_obj(ARG&& arg); 1) 如果我們傳遞 lvalue 給 acquire_obj(),則 ARG 就會被推導為 ARG&,因此如下程式碼的第二行,acquire_obj 被推導為: TYPE* acquire_obj(ARG& &&)。 1 ARG arg; 2 acquire_obj(arg); 然後根據前面說的摺疊原則,我們得到原型如下的函式: TYPE* acquire_obj(ARG&); 2) 如果我們如下這樣傳遞 rvalue 給 acquire_obj(),則 ARG 就會被推導為 ARG。 acquire_obj(get_arg()); 最後,模板函式例項化為原型如下的函式:TYPE* acquire_obj(ARG&&); 綜上討論可見,原則 2 其實是有些令人討厭的,它與一般模板函式的引數型別推導並不一致,甚至可以說有些相背(主要在於 top level cv removal principle),這些隨處可見的例外增加了語言的複雜性,加大了學習和記憶的難度,是如此令人討厭,但在 c++ 中這種現象又那麼常見,真是無奈。