最近看了祁宇大哥的深入應用c++11中的用c++11提高程式效能部分,對右值引用做乙個小讀後感悟及總結,其實右值引用沒想象的那麼神秘:
c++11 增加了乙個新的型別,右值引用,標記為t&&。c++11中所有的值必屬於左值、將亡值、純右值,其中將亡值和純右值屬於右值,比如,非引用返回的臨時變數、運算表示式產生的臨時變數、原始字面量和lambda表示式等都是純右值,將要被移動的物件、t&&函式返回值、std::move返回值和轉換為t&&的型別的轉換函式的返回值屬於將亡值。
右值引用對程式效能的改進:
struct a
a(const a& a)
~a()
};a geta()
int main()
int main()
t&& 型別的變數並不一定是左值,應為t未定是如函式模板的型別自動推導或auto關鍵字時,t&&是乙個未定義型別(universal reference),這需要應用c++11的摺疊規則:
1)所有的右值應用摺疊刀右值應用上還是乙個右值引用。
2)所有的其他引用型別之間的疊加都將變成左值引用。
如:int w1, w2;
auto&& v1 = w1;// v1 是乙個左值,auto推導的是乙個左值型別。左值型別+右值型別=左值型別。
decltype(w1)&& v2 = w2;//將乙個左值付給乙個右值型別是不合法的
需要用move語義將左值轉換為右值,如下:
decltype(w1)&& v2 = std::move(w2);
move語義的唯一作用就是將乙個左值轉換為乙個右值,使我們可以通過右值引用使用該值,實現移動構造,它實際上並不移動任何東西。
如果有乙個很大的容器list:
std::listtokens;
//初始化tokens
std::listt = tokens; //需要大量的拷貝
std::listtokens;
std::listt = std::move(tokens); //move將左值轉換為了右值,然後就會呼叫右值引數的賦值靠別函式轉換資源的所有權,避免了深拷貝。
下面是乙個避免深拷貝的例子:
class mystring
public:
mystring()
mystring(const char *p)
mystring(const mystring&str)
mystring& operator=(const mystring&str)
return *this;
}virtual ~mystring()
mystring(mystring&& str)
mystring& operator=(mystring&& str)
return *this;}};
如果呼叫拷貝構造或賦值拷貝函式是,用move將左值轉換為右值就會呼叫右值引數的拷貝構造和賦值拷貝函式,從而避免了深拷貝,現在明白了移動語義的含義了吧,實際上就c++11增減了個新型別,然後過載物件的拷貝構造和賦值拷貝函式,在函式中將記憶體位址轉移給另乙個指標物件,將原來的指標物件付為null,move作用就是將乙個左值轉為右值一遍呼叫右值引數的函式。所以移動語義中的許可權轉移實際上就是堆記憶體位址的轉移。
c 11 右值引用
右值引用 是一種復合型別,跟c 的傳統引用很類似。為更準確地區分兩種型別,我們把傳統的c 引用稱為 左值引用 而使用 引用 這一術語時,我們的意思同時包含兩種引用 左值引用和右值引用。右值引用的行為跟左值引用類似,不同之處在於 右值引用可以繫結到臨時量 右值 而 非const的 左值引用卻不能繫結到...
C 11 右值引用
消除兩個物件互動時不必要的物件拷貝,節省運算儲存資源,提高效率。能夠更簡潔明確地定義泛型函式。1.右值引用 int a a 1 here,a is an lvalue 上述的a就是乙個左值。c 11中左值的宣告符號為 為了和左值區分,右值的宣告符號為 printreference const str...
C 11右值引用
c 11中引入的乙個非常重要的概念就是右值引用。理解右值引用是學習 移動語義 move semantics 的基礎。而要理解右值引用,就必須先區分左值與右值。對左值和右值的乙個最常見的誤解是 等號左邊的就是左值,等號右邊的就是右值。左值和右值都是針對表示式而言的,左值是指表示式結束後依然存在的持久物...