3 回答
TA貢獻1796條經驗 獲得超10個贊
C+03引用(在C+11中現在稱為lvalue引用)的最大區別是,它可以像臨時的那樣綁定到rvalue,而不必是Const。因此,這個語法現在是合法的:
T&&?r?=?T();
rvalue參考主要提供以下內容:
移動語義..現在可以定義一個移動構造函數和移動賦值操作符,它接受一個rvalue引用,而不是通常的const-lvalue引用。遷移功能類似于副本,只是它沒有義務保持源不變;實際上,它通常修改源,使其不再擁有移動的資源。這對于消除無關的副本是很好的,特別是在標準庫實現中。
例如,復制構造函數可能如下所示:
foo(foo?const&?other){
????this->length?=?other.length;
????this->ptr?=?new?int[other.length];
????copy(other.ptr,?other.ptr?+?other.length,?this->ptr);}如果這個構造函數是臨時的,那么這個副本就沒有必要了,因為我們知道這個臨時構造函數只會被銷毀,為什么不利用臨時分配的資源呢?在C+03中,無法阻止復制,因為我們無法確定我們是臨時傳遞的。在C+11中,我們可以重載一個移動構造函數:
foo(foo&&?other){
???this->length?=?other.length;
???this->ptr?=?other.ptr;
???other.length?=?0;
???other.ptr?=?nullptr;}注意這里最大的區別:Move構造函數實際上修改了它的參數。這將有效地“移動”臨時對象到正在構造的對象中,從而消除不必要的副本。
屬性顯式轉換為rvalue引用的臨時和非Const值引用將使用移動構造函數。std::move函數(它只執行轉換)。下面的代碼都調用移動構造函數f1和f2:
foo?f1((foo()));?//?Move?a?temporary?into?f1;?temporary?becomes?"empty"foo?f2?=?std::move(f1);?//?Move?f1?into?f2;?f1?is?now?"empty"
完美轉發..rvalue引用允許我們正確地轉發模板函數的參數。例如,這個工廠功能:
template?<typename?T,?typename?A1>std::unique_ptr<T>?factory(A1&?a1){
????return?std::unique_ptr<T>(new?T(a1));}如果我們打電話factory<foo>(5),這個論點將被推斷為int&,它不會綁定到文字5,即使foo構造函數采用int..好吧,我們可以用A1 const&,但如果foo接受非Const引用的構造函數參數?要建立一個真正通用的工廠功能,我們必須在A1&繼續A1 const&..如果工廠采用一個參數類型,那么這可能很好,但是每一個附加的參數類型都會將所需的重載設置為2,這很快就無法維護了。
rvalue引用通過允許標準庫定義std::forward函數,可以正確轉發lvalue/rvalue引用。
這使我們能夠像這樣定義工廠函數:
template?<typename?T,?typename?A1>std::unique_ptr<T>?factory(A1&&?a1){
????return?std::unique_ptr<T>(new?T(std::forward<A1>(a1)));}現在,參數的rvalue/lvalue-ness在傳遞給T的構造函數,這意味著如果使用rvalue調用工廠,T用rvalue調用工廠的構造函數。如果使用lvalue調用工廠,T它的構造函數是用lvalue調用的。改進后的工廠函數可以工作,因為有一個特殊的規則:
函數參數類型為
T&&哪里T是模板參數,函數參數是類型的lvalue。A,類型A&用于模板參數推導。
因此,我們可以像這樣使用工廠:
auto?p1?=?factory<foo>(foo());?//?calls?foo(foo&&)auto?p2?=?factory<foo>(*p1);???//?calls?foo(foo?const&)
重要參考屬性:
- 為了解決過載問題,
lvalue更喜歡綁定于lvalue引用,rvalue更喜歡綁定而不是rvalue引用。
..因此,臨時人員為什么更喜歡調用移動構造函數/移動賦值操作符,而不是復制構造函數/賦值運算符。 rvalue引用將隱式綁定到rvalue和作為隱式轉換結果的臨時變量。
..E.
格式良好,因為Float是隱式可轉換為int的;引用將是臨時的,這是轉換的結果。float f = 0f; int&& i = f;命名的rvalue引用是lvalue。未命名的rvalue引用是rvalue。
這一點很重要,請理解為什么
打電話是必要的,因為:std::movefoo&& r = foo(); foo f = std::move(r);
TA貢獻1802條經驗 獲得超5個贊
指.的術語T&&?與類型扣除一起使用時(如用于完美轉發)被通俗地稱為轉發參考..“普遍參考”一詞是由ScottMeyers發明的
這是因為它可以是r值,也可以是l值。
例如:
//?templatetemplate<class?T>?foo(T&&?t)?{?...?}//?autoauto&&?t?=?...;//?typedeftypedef?...?T;T&&?t?=?...;//?decltypedecltype(...)&&?t?=?...;- 3 回答
- 0 關注
- 840 瀏覽
添加回答
舉報
