new 和 delete
C++的內存申請和釋放是通過 new 和 delete 實現的, 而new 和 delete 其實就是通過 malloc 和 free 實現的。
new 申請內存分為三個步驟:
- 調用 operator new 函數分配目標類型的內存大小,operator new 函數內部就是調用的 malloc 函數。
- 將申請得到的內存塊強制轉換為目標類型指針。
- 通過指針調用目標的構造函數(只有編譯器可以這樣直接調用構造函數)。
delete 釋放內存分為兩個步驟:
- 調用對象的析構函數。
- 調用 operator delete 函數釋放對象內存,operator delete 函數內部就是調用的 free 函數。
array new 和 array delete
array new 是申請多個對象的內存。
Cookie
通過 malloc 分配的內存,會在內存前后加上 cookie,以記錄內存分配的總大小,這里以包含三個 int 數據的 Demo 類為例:
上面 61h 存儲的就是內存塊的大小,其中最低位用於表示是否已分配(1表示已分配,0表示已回收),其中的 3 記錄了分配對象的數量。
當申請內存后,返回的指針指向數據開始處(00481c34),而使用 delete[] 釋放時,指針會指向00481c30,從而可以根據對象的數量調用相應次數的析構函數。如果使用 delete 釋放的話,它不會去00481c30地址獲取對象的長度,而是直接釋放00481c34位置處的對象。
所以,new[] 和 delete[] 需要配合使用,但是如果對象的類型是內置類型或者是無自定義的析構函數的類類型,是可以使用 delete 來釋放 new[] 對象的。否則使用 delete 來釋放對象的話,對象所分配的內存空間可以釋放,但是只會調用第一個對象的析構函數,可能導致內存泄漏。
對於 cookie,可以從運行速度和空間使用兩個方面去進行改進:
- 減少 malloc 的調用次數(雖然 malloc 的速度很快)。
- 每一個 new 的對象都會有上下兩個 cookie,可以預先申請一塊內存池,然后供對象實例化,這樣只會在這一整塊的內存池上下有 cookie,同時也可以減少 malloc 的調用次數。
(關於內存池可以看下一篇文章 C++內存管理:簡易內存池的實現 )
參考: