淺拷貝與深拷貝 拷貝控制總結

2021-07-13 11:08:17 字數 1499 閱讀 8072

class a

;class b

~b()

/* b(const b &temp)

*/};void sayhello(b x)

int main()

//程式崩潰!這裡的錯誤原因是編譯器在生成預設拷貝建構函式的時候執行了淺拷貝。上面被注釋掉的程式就是編譯器自動新增的部分。從而導致在sayhello中向x傳遞值時,呼叫了執行淺拷貝的預設拷貝建構函式使得x物件和b物件中的值完全一致,包括p指標的值,在x離開作用域(也就是sayhello函式結束),x發生析構,呼叫delete銷毀了指標p,同時在main函式結束的時候,析構b時又會呼叫一次delete刪除指標p。也就是本程式會delete乙個已經被delete的指標。可以做如下改進,來修復程式:

class b

~b()

b(const b &temp)

};

拷貝建構函式:

1.如果乙個建構函式的第乙個引數是自身類型別的引用,且任何額外引數都有預設值,則此建構函式是拷貝建構函式。(拷貝建構函式被用來初始化非引用類型別引數,這一特性解釋了為什麼拷貝建構函式自己的引數必須是引用型別。如果其引數不是引用型別,則呼叫永遠也不會成功——為了呼叫拷貝建構函式,我們必須拷貝它的實參,但為了拷貝實參,我們又需要呼叫拷貝建構函式,如此無限迴圈。)

2.什麼地方呼叫?(在我們用=定義變數時會發生;將乙個物件作為實參傳遞給乙個非引用型別的形參;從乙個返回型別為非引用型別的函式返回乙個物件;用花括號列表初始化乙個陣列中的元素或乙個聚合類中的成員。)

拷貝賦值運算子:

1.賦值運算子通常應該返回乙個指向其左側運算物件的引用。

析構函式:

1.沒有返回值,也不接受引數。(由於不接受引數,因此它不能被過載。對乙個給定類,只會有唯一乙個析構函式。)

1.需要析構函式的類也需要拷貝和賦值操作。

2.需要拷貝操作的類也需要賦值操作,反之亦然。(例子:考慮乙個類為每個物件分配乙個獨有的、唯一的序號。這個類需要乙個拷貝建構函式為每個新建立的物件生成乙個新的、獨一無二的序號。除此之外,這個拷貝建構函式從給定物件拷貝所有其他資料成員。這個類還需要自定義拷貝賦值運算子來避免將序號賦予目的物件。但是,這個類不需要自定義析構函式。)

顯示地要求編譯器生成合成的版本。

通知編譯器(以及我們**的讀者),我們不希望定義這些成員。(不能刪除析構函式)

重點:希望阻止拷貝的類應該使用=delete來定義它們自己的拷貝建構函式和拷貝賦值運算子,而不應該將它們宣告為private的。(新標準之前這樣做)

物件移動(在物件拷貝後就立即被銷毀的情況下,移動而非拷貝物件會大幅度提公升效能):

1.右值引用:&&,只能繫結到乙個將要銷毀的物件。

2.移動建構函式

3.移動賦值運算子

「淺拷貝」與「深拷貝」

c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...

淺拷貝與深拷貝

淺拷貝 1 2 myclass a,b a b 為了封裝性和解耦,同型別的兩個物件之間進行賦值操作時,所有成員變數被複製,包括私有成員 指標變數。類的成員函式在傳遞或返回物件時都會進行物件複製產生臨時物件,比如函式呼叫時實參變為形參,以及函式返回物件。考慮到效能和使用者要求不同,編譯器不複製物件內部...

「淺拷貝」與「深拷貝」

c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...