詳細解析 為什麼要寫自定義拷貝建構函式和賦值運算子

2021-05-22 19:49:50 字數 1593 閱讀 3629

//**********************

//**ch18_7.cpp**

//**********************

#include

#include

class name

name(char* pn)

name(name & s)

~name()

name & operator =(name & s)//

賦值運算子

void display()

protected:

void copyname(char* pn);

void deletename();

char* pname; };

void name::copyname(char* pn)

void name::deletename() }

void main()

在建構函式中該儲存區是從堆中分配來的,存在淺拷貝問題,必須自定義賦值運算子和拷貝建構函式。

賦值運算子以

operator=()

的名稱出現,看起來像乙個析構函式後面跟著拷貝建構函式。

就是這個**:

name & operator =(name & s)//

賦值運算子

void copyname(char* pn)

通常賦值運算子有兩部分,第一部分與析構函式類似,在其中取消物件已經占用的資源。第二部分與拷貝函式類似,在其中分配新的資源。(就是上面的**。)

其實上面就是深拷貝的情況了。堆分配的資源最後得

delete

釋放。而那樣會引起二義性,會第二次釋放已經釋放的資源,已經釋放的資源的指標早就已經成為野指標了,再對那塊未知的位置釋放空間會造成錯誤甚至程式崩潰。

如圖就是:

delete

無論誰先釋放其空間

對方都會釋放乙個無法找到的空間可能。因為原來的那個空間的位址早就不存在了。

那麼上面**怎麼解決的呢?

解決辦法就是在賦值的時候處理下。過程如下:

建立兩個物件,

a,b。然後為

a存放寫資源,在把

a賦值給

b的時候由賦值運算子函式來處理了。

看圖:本來是:

name a("claudette");

name b("temporary");

然後:上面圖的演示正是**的實現的效果。

a的資源和

b的資源各自乙份。

delete

釋放的時候也不會造成因無法釋放未知空間而崩潰了。

上面的討論到此為止。

ps

那麼有人可能再想,那麼麻煩上面操作,我狠一點,既然釋放會出問題那麼我不用

delete

釋放堆空間不就行了。他是根據這句話來的:「堆物件的作用域是整個程式生命期,所以除非程式執行完畢,否則堆物件作用域不會到期。」

確實這樣的確可以防止那種情況,但是代價是記憶體的占用比較大了,一旦程式大了一直開闢不釋放可能會記憶體溢位。故使用上面自定義複製運算子和自定義拷貝建構函式是很有用的。

參考文獻:《c++程式設計教程--錢能》

谷歌瀏覽器為什麼不能自定義安裝路徑?

久病成名醫。在經歷了電腦最近的備份 崩潰和恢復後,我對朝夕相處的windows又多了幾分了解。windows 7是windows xp之後微軟最成功的作業系統,也是之後windows 8和10的基礎,因此本文介紹的內容都以windows 7為環境。開啟檔案管理器 即開始選單中選擇計算機 在工具欄的 ...

為什麼Go中有的自定義error會導致記憶體溢位

分享乙個在go tour上看到的練習題,練習裡要求使用者自己定義乙個錯誤型別,實現error介面,函式在引數不滿足條件的時候返回自定義的錯誤型別的值。練習中特別提示使用者不要在實現的error方法裡直接使用fmt.sprint e 以避免造成程式記憶體溢位。下面貼一下具體的練習題 從之前的練習中複製...

mysql主鍵自增為什麼比隨機和自定義快?

1 如果表使用自增主鍵,那麼每次插入新的記錄,記錄就會順序新增到當前索引節點的後續位置,當一頁寫滿,就會自動開闢乙個新的頁 2 如果使用非自增主鍵 如果身份證號或學號等 由於每次插入主鍵的值近似於隨機,因此每次新紀錄都要被插到現有索引頁得中間某個位置,此時mysql不得不為了將新記錄插到合適位置而移...