拷貝建構函式 拷貝賦值運算子的總結

2021-10-08 20:27:22 字數 2153 閱讀 1796

一般編譯器會自定義預設的拷貝建構函式,但是當類中含有指標成員時,常常需要我們自己定義拷貝建構函式。

基本原則:1、當我們需要自定義析構函式時,通常也需要自定義拷貝建構函式。

2、需要拷貝建構函式時通常也需要自定義拷貝賦值運算子,反之亦然。

有兩種拷貝方式,深拷貝和淺拷貝。

當我們自定義的類中有指標型別的資料成員時,深拷貝會更加安全。所謂深拷貝就是開闢一塊新的記憶體空間,將另乙個物件的成員逐一拷貝到新的記憶體空間。

下面考慮自己實現乙個string類,主要是自己實現建構函式、析構函式、拷貝建構函式、拷貝賦值運算子。

class

mystring

;//建構函式

mystring::

mystring

(const

char

* str)

else

}//析構函式

mystring::

~mystring()

//拷貝建構函式

mystring::

mystring

(const mystring& other)

//傳參為const& 加分點

//過載賦值運算子

//1、返回型別為類的引用型別,返回*this

//2、傳入引數必須為const 引用型別

//3、釋放原來指標的記憶體

//4、刪除原來的指標之前必須要判斷引數與this是不是指向同乙個位址,是則返回*this

mystring& mystring::

operator=(

const mystring& other)

1、形參為const引用型別,防止改變傳入的實參。

2、實現深拷貝,先釋放原來的記憶體,再申請新的記憶體空間,將拷貝物件的字串拷貝到新記憶體空間中。

如果是淺拷貝,當兩個string類指向同一塊位址空間時,乙個string呼叫了析構,釋放了記憶體空間,此時另乙個string所指向的位址是沒有意義的,如果這時候呼叫string訪問這塊已經**的記憶體將產生未知行為。

深拷貝就不會有這樣的問題,因為重新申請了新的記憶體,但是深拷貝效率上會很慢。

返回型別為引用型別,返回*this(如果返回值型別,將呼叫拷貝建構函式)

形參為const 引用型別;(const 說明不改變=右側的值,引用傳參不會呼叫拷貝)

要考慮自賦值的操作,即判同測試,因為賦值之前要釋放『=』左側變數的記憶體空間,避免把自身的記憶體給釋放掉;

避免記憶體洩漏,當不是自賦值時,先釋放掉原來的內記憶體空間。

當我們需要實現類似智慧型指標shared_ptr時,拷貝的操作常常會是淺拷貝,只需要拷貝指標本身,拷貝之後的指標指向同一塊記憶體,不需要申請新的記憶體空間,但是同時需要維護乙個引用計數記錄該記憶體被共享的次數。

引用計數需要用指標實現,因為多個變數共用同乙個引用計數,儲存在堆記憶體中。

考慮實現乙個簡單的智慧型指標:

class

hasptr

~hasptr()

}//拷貝建構函式,ps指向同乙個記憶體,共享同乙個引用計數

hasptr

(const hasptr& rhs)

hasptr&

operator=(

const hasptr& rhs)

ps = rhs.ps;

//淺拷貝

use = rhs.use;

++* use;

return

*this;}

private

: string* ps;

// size_t* use;

//引用計數

};

初始化引用計數指標,初始值為1;

初始化指標成員;

每次呼叫析構函式將引用值減一,當引用值為0時銷魂物件釋放記憶體空間

指標成員直接賦指標值,不需要深拷貝

引用計數指標變數值也是直接賦值,引用計數加1

形參依然為const &型別

1、返回型別為&,返回*this,形參為const &;

2、首先處理自賦值,先經行判同測試;

3、「=」 左側變數引用計數值減一,判斷若引用計數值為0 則呼叫delete釋放記憶體;

4、指標成員直接賦值,不需要申請新記憶體;

5、右側變數引用計數值加一;

拷貝建構函式和賦值運算子

把引數傳遞給函式有三種方法,一種是值傳遞,一種是傳位址,還有一種是傳引用。前者與後兩者不同的地方在於 當使用值傳遞的時候,會在函式裡面生成傳遞引數的乙個副本,這個副本的內容是按位從原始引數那裡複製過來的,兩者的內容是相同的。當原始引數是乙個類的物件時,它也會產生乙個物件的副本,不過在這裡要注意。一般...

拷貝建構函式與賦值運算子

物件的 生命週期 管理意味著完全地控制物件的誕生 繁殖和消亡的過程。使用拷貝建構函式和賦值運算子,可以更快的進行物件的繁殖操作。拷貝建構函式是一種建構函式,其原型類似於 classname const classname x 賦值建構函式的作用就是建立乙個物件,該物件是同乙個類中已有物件的精確副本。...

拷貝建構函式和賦值運算子

來自 本文主要介紹了拷貝建構函式和賦值運算子的區別,以及在什麼時候呼叫拷貝建構函式 什麼情況下呼叫賦值運算子。最後,簡單的分析了下深拷貝和淺拷貝的問題。在預設情況下 使用者沒有定義,但是也沒有顯式的刪除 編譯器會自動的隱式生成乙個拷貝建構函式和賦值運算子。但使用者可以使用delete來指定不生成拷貝...