本節書摘來自異步社群出版社《c++程式設計風格(修訂版)》一書中的第2章,第2.6節,作者:【美】tom cargill,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
c++程式設計風格(修訂版)
string 類在管理動态記憶體時還存在着第二個問題:“記憶體洩漏”,當所有使用 new 來配置設定的動 态記憶體并沒有都使用 delete 來進行釋放時,就會發生記憶體洩漏。string 類中的記憶體洩漏既不在構 造函數中,也不在析構函數中。我們可以看到,在每個構造函數中僅執行一次 new,以獲得一個 指向字元數組的指針,并把這個指針儲存在 s 中。在 string 對象中總是包含有一個數組來存儲字 符串,并且這塊記憶體在對象生存期結束時,将會通過在析構函數中調用 delete[] s 來進行釋放。
在 concat() 中存在着記憶體洩漏,因為在函數中配置設定新的數組時,并沒有釋放對象中目前的數 組。當 concat() 執行下面的語句時:

s 馬上被一個新的指針值覆寫,而前一個指針值則被抛棄了,這就使得前一個指針所指向字 符數組成為了一塊垃圾記憶體。
為了改正這個記憶體洩漏問題,concat() 必須保證原有的數組一定要被删除。我們在每次使用 new 時都将建立一個動态對象(在本例中是一個動态數組),對于每個動态對象,很關鍵的一件事就是 建立一個“所有者”——當不再需要動态記憶體時,所有者應該負責銷毀動态對象。最簡單的所有者 政策就是,将執行 new 操作的對象作為動态對象的所有者,并且必須由所有者來負責删除動态對象。 根據這個政策,string 類就必須負責删除所有在構造函數或者其他的成員函數中配置設定的字元數組。
對于每個 new操作,都要有相應的 delete操作。
對于 concat() 中的問題,解決方案并不像在執行 new 之前增加一條 delete[] s 語句這樣簡單。 下面的代碼并不足以解決 concat() 中的問題:
上面的 concat() 中有什麼樣的錯誤?假設 x 和 y 是 string 類的執行個體,并且我們通過表達式 x.concat(y,x) 來調用 concat() 函數。那麼,在 concat() 中,函數将通過兩種方法來通路對象 x : this 指針和參數 b 都是指向 x。我們可以看到,在執行 concat() 時,x.s 指向的數組在通過 b.s 傳 遞給 strcpy() 之前,就已經通過 this->s 删除了。等到執行 strcpy() 時,字元數組已經釋放了,甚 至還可能被 concat() 中的 new 進行了重新配置設定。
要改正 concat() 中的記憶體洩漏,delete 語句隻能添加在新的字元串建立之後:
本文僅用于學習和交流目的,不代表異步社群觀點。非商業轉載請注明作譯者、出處,并保留本文的原始連結。