C 的拷貝構造和移動構造

2021-10-05 10:22:47 字數 1884 閱讀 6805

如果乙個建構函式的第乙個引數是自身類型別的引用,且任何額外引數都沒有預設值,則此建構函式是拷貝建構函式。(《c++primer,第五版》)

class foo

;

類的成員中有指標時,使用深拷貝。

#include using namespace std;

class foo

foo(const foo&)= default; //拷貝建構函式

foo& operator=(const foo&) = default; //拷貝賦值運算子

int* pint;

};//淺拷貝,foo1和foo2中的pint指向同一塊記憶體位址

foo foo1;

foo foo2(foo1);

//深拷貝

class cop

cop(const cop& cop)

int* pint;

};//深拷貝,cop1和cop2中pint指向不同記憶體

cop cop1;

cop cop2(cop1);

在某些情況下(函式返回物件引用),物件拷貝後立即就被消耗了。拷貝構造就回造成效能上的浪費,而且深拷貝也會造成浪費。移動構造可以避免這種情況的發生。

為了支援移動構造,c++11引入了右值引用。

右值引用:必須繫結到右值的引用,通過&&來獲得右值引用,類似左值引用(常規引用),右值應用也是一塊記憶體的別名。

右值:字面常量、在表示式求值過程中臨時建立的物件,這些使用過後就被銷毀的資源。不同於左值的持久狀態。

因此,右值引用只能繫結到將要被銷毀的物件上,左值引用只能繫結到持久的物件上。

//例子**於  《c++primer 第五版》

int i = 42;

int& r = i; //正確,i是左值

int&& rr = i; //錯誤

int& r2 = i * 42; //錯誤,i*42是右值,用完即銷毀

const int& r3 = i * 42; //正確,隱式轉換為左值後,r3引用

int&& rr2 = i * 42; //正確,繫結右值

int&& rr1 = 42;  //正確,字面常量是右值

int&& rr2 = rr1;  //錯誤,rr1左值

變數都是左值,因此無法將右值引用繫結到乙個右值引用型別的變數上。

如果要將右值引用繫結到左值上,可以通過move函式來獲得左值的右值引用型別。對乙個左值呼叫move函式後,除了對該左值賦值和銷毀外,不再使用它。

int i = 42;

int&& rr = move(i);

//i和rr引用同一塊記憶體

i = 32;

cout << i << endl;

cout << rr << endl;

移動建構函式依靠右值引用特性來將來改變記憶體的管理者,而不同於拷貝構造對記憶體進行拷貝。

移動構造:第乙個引數是該類型別的乙個右值引用,且任何額外的引數都必須有預設實參。使用移動建構函式必須確保銷毀移後源物件是無害的(不會重複釋放同一塊記憶體)。

cop(cop&& cop) noexcept : pint(cop.pint)

cop& operator=(cop&& cop) noexcept

cop retcop()

//呼叫移動賦值運算子,cop3中pint接管retcop返回物件中的pint指向記憶體

cop cop3 = retcop();

noexcept承諾函式不丟擲異常,標準庫對這個函式不做額外處理。

C 移動建構函式和拷貝建構函式

我們用物件 a初始化物件b 後物件 a我們就不在使用 了,但是物件a的空間還在呀 在析構之前 既然拷貝建構函式,實際上就是把a物件的內容複製乙份到b中,那麼為什麼我們不能直接使用a的空間呢?這樣就避免了新的空間的分配,大大降低了 構造的成本 這就是移動建構函式設計的初衷 拷貝建構函式 中,對於指標,...

C 中的拷貝構造,賦值和移動構造

在說明這幾個名詞時,我們需要定義乙個測試類person,person類的測試環境為vs2013 一般情況下,在物件宣告時用拷貝建構函式對物件進行初始化 在編譯器進行優化的時候也會使用移動構造函 數 在有臨時物件產生的情況下 這樣效率會高一些,如避免深度拷貝之類的操作 一旦初始化之後,在 進行 運算將...

c 11 移動構造 移動賦值 拷貝構造

最近對準備深入學習一下c 11所有的新特性,今天研究了一下c 11的std move和std forward,在研究這個的時候,需要對c 0xx的拷貝構造,拷貝賦值有一些了解.這個不知道的自己去了解,這裡記錄一下c 11新加的移動版本 移動構造 移動賦值和拷貝構造 拷貝賦值的比較,文章引用 現代c ...