c 11 右值引用

2021-07-05 13:55:42 字數 1588 閱讀 4286

最近看了祁宇大哥的深入應用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 的基礎。而要理解右值引用,就必須先區分左值與右值。對左值和右值的乙個最常見的誤解是 等號左邊的就是左值,等號右邊的就是右值。左值和右值都是針對表示式而言的,左值是指表示式結束後依然存在的持久物...