右值引用和移動語義

2021-09-11 02:51:32 字數 1910 閱讀 1232

在c++當中,所有的變數和表示式都被分為左值和右值。所謂的左值,就是可以被定址的非臨時變數。右值就是無法被定址的臨時變數。左值引用用』&『符號表示,右值引用用』&&『符號表示。

// 左值引用

int n;

int *np = new int;

const int cn = 100;

int & nr = n;

int & npr = *np;

const int & cnr = cn;

// 右值引用

int x = 100;

int && r1 = x + 1;

int && r2 = 100;

int && r3 = std::sqrt(2.1);

左值引用就是我們熟知的引用,只能把可以定址的非臨時變數指向引用。而「x + 1」表示式,sqrt()函式,100,都會返回乙個臨時變數,這時需要使用右值引用。所以,右值引用就是來彌補右值引用的不足,實現臨時變數的引用。

我們有乙個建立vetor的函式:

using namespace std;

vectorfoo()

vectoritem(foo());

在生成item時,foo函式會建立乙個臨時變數,再使用這個臨時變數作為引數來初始化item變數,最後再將臨時變數銷毀。這中間做了大量的無用功,foo返回的臨時變數就是我們所需要的,那為什麼不能直接把他的資料位址拿過來直接用呢?解決這個問題的就是移動語義。

移動語義將資源 ( 堆,系統物件等 ) 從乙個物件轉移到另乙個物件,這樣能夠減少不必要的臨時物件的建立、拷貝以及銷毀。

而為了實現移動語義,我們建立2個複製建構函式,乙個用左值引用作為實參,乙個用右值引用作為實參。這就是右值引用的意義。右值引用來指向臨時變數,並且為類來標識那個實現移動語義的複製建構函式。

為了實現移動語義,我們需要在類中建立移動建構函式和移動賦值運算子。他們接收右值引用作為引數,實現對臨時變數中資料所有權的奪取。下面是個簡單的例子。

#include class mystring;

mystring::mystring(const char* s = "c++")

mystring::mystring(const mystring & r)

mystring& mystring::operator=(const mystring & r)

mystring::mystring(mystring && r)

mystring& mystring::operator=(mystring && r)

mystring::~mystring()

上述**有2點需要注意的地方:

1、移動建構函式和移動賦值運算子函式中,最後都要將臨時變數的指標指向nullptr。因為臨時變數最後還是要釋放掉,如果不指向0位址,我們轉移的資料也會隨變數一起釋放掉。同時,也防止乙個位址被多次析構。

2、移動建構函式和移動賦值運算子函式的右值引用引數不能加const修飾符。因為我們要修改右值引用的指標,使其指向0位址,所以不能和複製建構函式一樣,加上const關鍵字。

在許多場景中,我們可能也需要對左值也使用移動語義。比如我們從乙個陣列中只獲取乙個變數,之後整個陣列都棄用了。我們可以使用一些方法,把左值引用作為右值引用傳遞進函式。下面介紹2種方法:

1、使用static_cast<>實現強制型別轉換

mystring a("c");

mystring b(static_cast(a));

2、使用utility中的move函式

#include mystring a("c");

mystring b(std::move(a));

C 移動語義和右值引用

移動語義類似於在計算機中移動檔案的情形 實際檔案還留在原來的地方,而只修改記錄。例如有乙個函式,它返回乙個vector物件 要實現移動語義,需要讓編譯器知道什麼時候需要複製,什麼時候不需要。這就是右值引用發揮作用的地方。可定義兩個建構函式,其中乙個是常規複製建構函式,它使用const左值引用作為引數...

移動語義和右值引用(C 11)

左值 可以取位址 有名字的 右值 不能取位址 沒名字的 傳統的c 引用稱為左值引用,使得標誌符關聯到左值。c 11新增了右值引用,使用 表示。引入右值引用的主要目的之一是實現移動語義。在複製物件時,實現物件的移動而非拷貝。通過移動建構函式 移動賦值運算子實現 函式的引數為右值引用,函式內部並非深度複...

C 11 右值引用和移動語義

因為工作室要求寫技術部落格記錄學習到的知識點,自己之前是沒有寫過部落格的,所以現在用一篇介紹右值引用和移動語義的部落格作為部落格的第一篇,可能對於移動語義的理解還不夠深刻,但可以作為乙個簡單的介紹部落格 要理解好右值引用首先要知道什麼是左值?什麼是右值?1.左值是表示式結束後依然存在的持久化物件 2...