//**********************
//**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不得不為了將新記錄插到合適位置而移...