賦值運算子函式

2021-10-19 20:19:11 字數 2208 閱讀 8917

賦值運算子函式作為類的乙個成員函式,主要用於物件之間的賦值。類一般都有預設的賦值運算子函式,然而預設賦值運算子函式只會淺拷貝,無法滿足需求,有時還會產生致命錯誤。

如下:

class

cstring

cstring

(const cstring& str)

:_buf

(nullptr

)cstring

(const

char

* str)

:_buf

(nullptr)~

cstring()

}private

:char

* _buf;};

intmain()

}

如上**所示,如果使用預設賦值運算子函式,str2 = str1;str2和str1將會指向同一塊記憶體位址,當離開**塊作用域之後,str1和str2都將析構,這裡將產生double free 記憶體錯誤。

對於這種需要深拷貝的賦值運算子函式需要自己定義。

下面是針對cstring類的幾種賦值運算子函式的實現:

cstring& cstring::

operator=(

const cstring& str)

delete

_buf;

_buf =

nullptr

;const

int size =

strlen

(str._buf)+1

; _buf =

newchar

[strlen

(str._buf)+1

];memset

(_buf,

0, size)

;strcpy

(_buf, str._buf)

;return

*this

;}

如上賦值運算子返回值定義成引用型別,方便連續賦值,如str1 = str2 = str3;

賦值運算子引數定義成物件的常量引用,主要保證不會修改被賦值的物件;

實現中,先判斷是否是物件自己,如果是則返回自己,

接著釋放_buf記憶體,並置空

最後申請新的記憶體,將引數str中_buf資料拷貝到當前物件的buf中。

以上實現就是乙個深拷貝。但是嚴格來講也是存在問題的,當new char 丟擲異常時,由於在這之前已經delete _buf,則當前物件就不能在保持有效狀態,這就違背了異常安全性原則。好的做法應該是先申請記憶體,再釋放記憶體,如下:

cstring& cstring::

operator=(

const cstring& str)

const

int size =

strlen

(str._buf)+1

;char

* buf =

newchar

[strlen

(str._buf)+1

];memset

(_buf,

0, size)

;delete

_buf;

_buf = buf;

strcpy

(_buf, str._buf)

;return

*this

;}

還有另一種更優雅的實現:

cstring& cstring::

operator=(

const cstring& str)

cstring strtemp

(str)

;char

* buf = strtemp._buf;

strtemp._buf = _buf;

_buf = buf;

return

*this

;}

這種實現將new出現異常的情況轉移到拷貝建構函式中,即便出現異常也不會影響當前物件的狀態。

一般我們自己定義的類都需要實現賦值運算子函式,特別是含有動態記憶體的物件。賦值運算子函式要保證物件的賦值是深拷貝,而且在實現的過程中也要注意異常安全性,這樣才能能寫出健壯而優雅的**。

賦值運算子函式

賦值運算子函式的 需要關注幾點 1 是否把返回值的型別宣告為該型別的引用,並在函式結束前返回例項自身的引用 即 this 只有返回乙個引用,才可以允許連續賦值。否則如果函式的返回值void,該賦值運算子將不能做連續賦值。2 是否把傳入的引數的型別宣告為常量引用。引數宣告為引用可以避免無謂的消耗,提高...

賦值運算子函式

題目 如下為型別cmystring的宣告,請為該型別新增賦值運算子函式。class cmystring 1 經典解法,初級程式設計師 cmystring cmystring operator const cmystring str 2 考慮異常安全的解法,高階程式設計師 cmystring cmys...

賦值運算子函式

型別宣告如下 class cmystring 請為上型別新增賦值運算子函式.經典解法 cmystring cmystring operator const cmystring str 考慮異常安全性解法 cmystring cmystring operator const cmystring str...