注意類型別的拷貝行為

2021-08-01 14:03:12 字數 989 閱讀 3649

當乙個類被拷貝時,會面臨許多的問題,其中之一就是對於乙個類所擁有的資源能否被複製的問題。比如,自己要建立乙個智慧型指標型別的類,那麼對於這個類的拷貝初始化怎麼辦呢,如果直接賦值指標,那會造成非常嚴重的後果,這顯然是不可取的。那麼我們該怎麼做呢,在effective中有四種方法禁止不合理的拷貝行為。

1.禁止賦值:當自定義的類物件被複製並不合理的時候,那麼可以將copying操作宣告為禁止的,在c++11中,可以直接令copying函式為=delete,在老版本的編譯器環境下,可以把相關函式定義為private的,來阻止使用者使用。

2.對底層資源使用「引用計數法」:即我們可以使用智慧型指標,來管理自己定義類中的底層資源,當底層資源被不在被需要時,會自動釋放,當底層資源引用計數不為零時被保留。並且,類不用再實現析構函式,因為當呼叫析構函式時會自動呼叫非靜態成員的析構函式,而對於智慧型指標,會自動呼叫其析構函式釋放相應的底層資源。    注:使用share_ptr的好處不止在於引用計數,還在於可以自定義「刪除器」,在構造是傳入乙個函式物件即可。(關於刪除器不明白的可以參考相關書籍或者提問)

3.複製底部資源:即所謂的深複製。

4.轉移底部資源的擁有權:在c++11的新標準中,資源的擁有權會從被複製物轉移到目標物,即所謂的移動建構函式和移動賦值函式。而在新標準中對於乙個右值,由於其特性是即將銷毀並且沒有其他的使用者,所以對乙個右值使用移動操作是安全且合法的,而對於乙個左值要進行移動操作則需要呼叫std::move()函式強制生成乙個右值引用,而當你呼叫move時意味著承諾和責任,即你所引用的那個左值是不能在被使用,且其在被移動後是處於安全可銷毀狀態的。在老標準中,由於沒有右值移動,所以可以在需要實現移動的類中自己編寫移動**,其行為類似auto_ptr。但是這意味著你必須保證其指揮使用到移動**,因為,其移動操作也是在拷貝建構函式中使用的,所以其將不存在拷貝操作。所以本方法僅僅在非常罕見的情況下適用。

拷貝行為會被編譯器自動建立出來,即所謂的預設行為。如果預設的行為不能滿足你的要求,則你得自己編寫他們!

所以類的資源的拷貝行為決定類物件的拷貝行為,這點必須牢記。

Item 14 資源管理類要特別注意拷貝行為

例如,假設你使用 c api 提供的 lock 和 unlock 函式去操縱 mutex 型別的互斥體物件 void lock mutex pm void unlock mutex pm 為了確保你從不會忘記解鎖乙個被你加了鎖的 mutex,你希望建立乙個類來管理鎖。raii 原則規定了這樣乙個類的...

c 筆記 類型別拷貝控制

乙個類通過定義五種特殊的成員函式來控制物件的拷貝,移動,賦值和銷毀操作,分別是拷貝建構函式 拷貝賦值建構函式 移動建構函式 移動賦值運算子和析構函式。拷貝和移動建構函式定義了當同型別的另乙個物件初始化本物件時,做什麼操作 拷貝和移動賦值運算子定義了乙個物件賦值給同型別的另乙個物件時,做什麼操作 析構...

為什麼引用型別string的行為卻是值型別

首先,我們需要知道string的如下特性 1.字串做引數,傳遞的是引用,只是乙個指標的複製,你修改引數的指向,影響不到呼叫它的函式中的那個指標所指向的內容 2.字串不可修改。你以任何一種形式修改了字串 等操作 源字串其實還在的,只是根據你的修改重新生成了乙個新的字串 3.如果需要修改,兩種方案,一是...