深入new和delete小結

2021-06-01 03:01:30 字數 1926 閱讀 3324

new和delete是c++中使用頻率非常高的兩個關鍵字,可以說c++記憶體操作的核心就在於這兩個關鍵字,近幾天閱讀了相關的文章,發現自己對於這兩個關鍵字的理解太過膚淺,因此做了一些個人總結。

首先要明確一點,new和delete所操作的記憶體全部是在堆區,這個區域的記憶體和棧區是不一樣的,不會自動釋放,因此一定要記得釋放不使用的記憶體,否則會造成記憶體洩露。new操作有兩種形式,一種是原始的new,一種是運算元組的new,二者本質上沒區別,只是操作的物件不同。對於系統內建的型別,new會直接分配定義好大小的記憶體區塊,而對於使用者自定義的型別,new會先呼叫建構函式,然後再分配記憶體區塊。c++編譯器會通過訪問自定義型別的內部成員來計算該型別的大小,打個比方,class a裡面有兩個資料成員,乙個是char,乙個是int,那麼該類物件所佔的記憶體大小就是8+4=12位元組。但是實際上,自定義型別的物件所佔的記憶體大小是大於理論值的,原因就是c++編譯器有乙個cookie機制,這個機制能讓自定義變數記錄一些變數的全域性資訊,而記憶體大小就包括在這些資訊裡。這個cookie機制和web技術中的cookie其實有相似的地方,都是一種類似快取的機制,有利於程式效率的提公升。這種機制帶來的乙個好處就是使用者在呼叫delete的時候再也不用指定記憶體的大小了,因為在呼叫delete的時候,編譯器會自動讀取cookie中分配記憶體的大小,從而直接釋放記憶體,而不必像new似的,需要臨時計算記憶體大小。而new的原理實際和new是一樣的,只不過new是對陣列中所有資料成員呼叫建構函式,然後分配記憶體,同理,delete也是對所有資料成員呼叫析構函式,然後釋放記憶體。

對new和delete的過載具有很大意義,特別是在處理記憶體洩露方面。原始的new和delete雖然提供了一些處理記憶體異常的方法,但是在記憶體洩露方面基本是靠程式設計師自覺的,如果乙個程式設計師忘記釋放某部分記憶體,編譯器不會提示錯誤。c++編譯器之所以這麼設計是有原因的,因為檢測記憶體洩露所付出的代價往往是非常大的,編譯器需要逐位檢查資料是否置零,這對於小型資料來說也許不算什麼,但如果對於集群資料來說,代價太大了,況且記憶體洩露的原因五花八門,這導致記憶體洩露在異常處理方面也會非常複雜,因此如果讓new和delete支援記憶體洩露檢測的話,它們的執行效率會下降非常多,而new和delete恰恰是c++中使用頻率最高的兩個操作,因此這類操作,效率肯定是放到第一位的,假如這類操作效率很低,對程式的負面影響是非常巨大的。但是這並不表示使用者不可以定製自己的new和delete操作符,假如程式對記憶體檢測的需求很高,那麼使用者完全可以過載這兩個操作符。

其實new的過載遠不是僅僅分配記憶體那麼簡單,在effective c++中,作者對new的過載做了比較深入的講解,按照書中的觀點,new除了分配記憶體,還有兩個事情要做,乙個是處理0位元組的情況,乙個是處理記憶體不夠的情況,處理0位元組的情況是把它當成1位元組來處理,而處理記憶體不夠的情況則需要借助於new_handler。new_handler是乙個全域性函式指標,指向乙個處理記憶體不夠的函式,這個指標通過中的set_new_handler函式來設定指向的物件。如果用**去實現的話,大概應該是這個樣子:

void * operator new(size_t size)  

new_handler globalhandler = std::set_new_handler(currenthandler);

std::cout<<"this is reloaded new"<

其中currenthandler是使用者自定義的記憶體出錯處理函式,而globalhandler則是系統的全域性出錯處理函式。這個函式既處理了0位元組情況,又處理了記憶體不夠的情況,並且可以正常分配記憶體,可以說完成了new的基本功能,使用者可以在這個基礎上做任何擴充套件,都應該是沒問題的。

而delete的過載則簡單的多,由於不用指定記憶體大小,所以只需資料指標即可,但是,同樣,delete需要處理空指標的情況,以保證delete的操作是安全的。那麼實現的**就是類似這種的:

void operator delete(void *rawmemory)

同樣,使用者可以在這個基礎上做任何擴充套件。

深入理解C語言的new 和delete

目錄 c 的動態記憶體管理方式和c語言不一樣,在c 中使用new和delete來替換c語言中的malloc和free。這裡有幾個點不一樣,1 new和delete是操作符,malloc和free是函式 我的理解是c 將new和delete約定為操作符而已,new和delete操作符過載函式本質上還是...

New和delete的原理

new和delete的原理 當我們在程式中寫下 new 和 delete 時,我們實際上呼叫的是 c 語言內建的 new operator 和 delete operator.所謂語言內建就是說我們不能更改其含義,它的功能總是一致的。以 new operator 為例,它總是先分配足夠的記憶體,而後...

多型與new和delete

在使用多型時,在new和delete時一定要保持原有物件型別,不能在new時就進行強制轉換,否則會在析構時出現問題。其他時候可以使用 如下面的例子 class cbase cbase virtual void call class cinherit public cbase cinherit vir...