C 記憶體管理基礎之new delete

2021-04-13 08:41:45 字數 2257 閱讀 4743

1. 分清operator new和new operator

全域性函式operator new通常這樣宣告:

void * operator new(size_t size);

返回值型別是void*,表示其返回的是乙個未經處理(raw)的指標,指向未初始化的記憶體。引數size_t確定分配多少記憶體。你能增加額外的引數過載函式operator new,但是第乙個引數型別必須是size_t。標頭檔案中有乙個很好的過載的例子,那就是placement new,它看上去象這樣:

void * operator new(size_t, void *location)

這初看上去有些陌生,但它卻是new操作符的一種常見過載方法,使用乙個額外的變數buffer,當new操作符隱含呼叫operator new函式時,把這個變數傳遞給它。被呼叫的operator new函式除了持有強制的引數size_t外,還必須接受void*指標引數,指向構造物件占用的記憶體空間。未被使用的(但是強制的)引數size_t沒有引數名字,以防止編譯器警告說它未被使用。在使用placement new的情況下,呼叫者已經獲得了指向記憶體的指標,因為呼叫者知道物件應該放在**。placement new需要做的就是返回傳遞給它的指標。

我們更經常使用的new是new操作符(new operator),而非操作符new(operator new),如當你使用new操作符構建乙個物件的時候,實際上做了兩件事情,一是呼叫operator new函式獲取記憶體,二是呼叫物件的建構函式,如:

string *ps = new string("hello, world!");

它完成與下面**相似的功能:

void *memory = operator new(sizeof(string));         // 為string物件得到未經處理的記憶體

call string::string("hello, world!") on *memory;     // 呼叫建構函式初始化記憶體中的物件

string *ps = static_cast(memory);           // ps指標指向新的物件

注意第二步中建構函式的呼叫只能由編譯器完成,使用者是不允許這樣操作的,也就是說如果你想建立乙個堆物件就必須用new操作符,不能直接像上面一樣呼叫建構函式來初始化堆物件。

new操作符(new operator)是編譯器內建的,其行為被語言固定下來,不受使用者控制。但是它們所呼叫的記憶體分配函式也就是操作符new(operator new)則可以根據需要進行過載。試著回顧new操作符(new operator)與操作符new(operator new)的關係,如果你想在堆上建立乙個物件,應該用new操作符。它既分配記憶體又為物件呼叫建構函式。如果你僅僅想分配記憶體,就應該呼叫operator new函式,它不會呼叫建構函式。如果你想定製自己獨有的記憶體分配過程,你應該過載全域性的operator new函式,然後使用new操作符,new操作符會呼叫你定製的operator new。如果你想在一塊已經獲得指標的記憶體裡建立乙個物件,應該使用placement new。

最後需要記住的一點是,delete和new一樣具有以上的特性,只是需要注意的一點是delte操作符中是首先呼叫物件的析構函式,然後再呼叫operator delete函式的。

2. 針對陣列的new和delete操作

建立陣列時new操作符(new)的行為與單個物件建立(new)有少許不同:

第一是記憶體不再呼叫用operator new函式進行分配,代替以operator new函式(常稱作array new)。它與operator new一樣能被過載,允許定製陣列的記憶體分配,就象定製單個物件記憶體分配一樣。

第二個不同是new操作時呼叫建構函式的數量。對於new而言,在陣列裡的每乙個物件的建構函式都必須被呼叫。

delete操作符的語義基本上和new相同,他們的實現類似這樣:

void * operator new(size_t size)

void operator delete(void* p)

3. operator new和delete函式的實現

operator new實際上總是以標準的c malloc()完成,雖然並沒有規定非得這麼做不可。同樣,operator delete也總是以標準得c free()來實現,不考慮異常處理的話他們類似下面的樣子:

extern void* operator new( size_t size )

return last_alloc;}

extern void operator delete( void *ptr )   

C 基礎 記憶體管理篇

記憶體管理是計算機程式設計最為基本的領域之一。在很多指令碼語言中,您不必擔心記憶體是如何管理的,這並不能使得記憶體管理的重要性有一點點降低。對實際程式設計來說,理解您的記憶體管理器的能力與 侷限性至關重要。在大部分系統語言中,比如 c 和 c 您必須進行記憶體管理。本文將介紹手工的 半手工的以及自動...

c基礎之記憶體管理

一 作用域 全域性變數和區域性變數 靜態全域性和區域性變數 總結 型別作用域 生命週期 區域性變數 int a 10 從變數定義到函式結束 區域性變數建立到函式結束 全域性變數 int a 10 整個專案檔案 程式建立到程式結束 static 區域性變數 int a 10 從變數定義到函式結束 程式...

c語言基礎 記憶體管理

1 malloc calloc 分配新的記憶體區域。calloc 在動態分配完記憶體後,自動初始化該記憶體空間為零,而 malloc 不初始化,裡邊資料是隨機的垃圾資料。2 realloc 調整已分配的記憶體區域。先判斷當前的指標是否有足夠的連續空間,如果有,擴大mem address指向的位址,並...