每個程序在執行時都會占用一塊可用的內存空間,用於存放動態分配的對象,此內存空間稱為自由存儲區或堆。
一.new和delete用法
如下幾行代碼:
int *pi=new int; int *pi=new int(); int *pi=new int(1024);
第一行這個new表達式在自由存儲區中分配創建了一個整形對象,並返回一個指向該對象的地址來初始化指針pi。第二行同一行,只是對指針pi指向的地址的值進行了初始化為0。第三行初始化為1024。
當動態創建的對象用完后必須釋放內存,避免造成內存泄漏,可以用delete來完成,new和delete是成對使用的,如下命令釋放pi指向的int型對象所占用的內存空間:
delete pi;
此時·pi盡管沒有定義,但仍然存放了它所指向對象的地址,然而pi所指向的內存已經被釋放,因此pi不再有效。建議一旦刪除指針所指向的對象,立即將指針置為0,這樣就清楚的表明指針不再指向任何對象。
p=NULL;
值得注意的是當執行下列表達式:
int pi=&i; delete pi;
編譯器一般不會報錯,因為編譯器通常不能斷定一個指針指向什么類型的對象,所以盡管這個語句是錯誤的,但在大多數編譯器上仍然能通過。
C++中允許動態創建const對象:
const int *pi=new const int(1024);
動態創建的const對象必須進行初始化,並且進行初始化后的值不能再改變。
當創建一個動態數組對象和進行內存釋放時,執行以下語句:
int *pi=new int[]; //指針pi所指向的數組未初始化 int *pi=new int[n]; //指針pi指向長度為n的數組,未初始化 int *pi=new int[](); //指針pi所指向的地址初始化為0 delete [] pi; //回收pi所指向的數組
二.malloc和free的用法
兩個函數的原型如下,他們都在頭文件stdlib.h中聲明。
void *malloc(size_t size); void free(void *pointer);
示例代碼如下:
int *p=(int *)malloc(100); //指向整型的指針p指向一個大小為100字節的內存的地址 int *p=(int *)malloc(25*sizeof(int)); //指向整型的指針p指向一個25個int整型空間的地址
因為malloc()函數的返回值類型為void *,所以需要在函數前面進行相應的強制類型轉換。當int占4個字節內存時,上述的兩個語句代碼獲得的內存空間大小是相同的。分配內存后必須驗證內存是否分配成功,完成后用free()釋放內存,完整語句如下。
int *p=(int *)malloc(int); if(pi==NULL) printf("Out of memory!\n"); free (p);
另外還有兩個分配內存的函數:calloc和realloc,他們的原型如下:
void *calloc(size_t num_elements,size_t element_size); void realloc(void *tr , size_t new_size);
malloc和calloc間的主要區別在於后者在返回指向內存的指針之前把它初始化為0。另一個區別是calloc的參數包括所需的元素的數量和每個元素的字節數。
realloc函數用於修改一個原先已經分配的內存塊的大小。可以使一塊內存擴大或縮小,如果擴大內存,則原來的內存塊保持不變,在內存尾部增加新的內存塊,切不進行初始化。如果縮小內存,則原來內存塊從尾部進行刪減。如果原先的內存塊無法擴充,則新開辟一塊內存,並復制原先的內存的內容,原先內存塊失效無法再進行訪問。
三.new和malloc的區別
a.屬性
new/delete是C++關鍵字,需要編譯器支持。malloc/free是庫函數,需要頭文件支持c。
b.參數
使用new操作符申請內存分配時無須指定內存塊的大小,編譯器會根據類型信息自行計算。而malloc則需要顯式地指出所需內存的尺寸。
c.返回類型
new操作符內存分配成功時,返回的是對象類型的指針,類型嚴格與對象匹配,無須進行類型轉換,故new是符合類型安全性的操作符。而malloc內存分配成功則是返回void * ,需要通過強制類型轉換將void*指針轉換成我們需要的類型。
e. 分配失敗
new內存分配失敗時,會拋出bac_alloc異常。malloc分配內存失敗時返回NULL。
f.自定義類型
new會先調用operator new函數,申請足夠的內存(通常底層使用malloc實現)。然后調用類型的構造函數,初始化成員變量,最后返回自定義類型指針。delete先調用析構函數,然后調用operator delete函數釋放內存(通常底層使用free實現)。
malloc/free是庫函數,只能動態的申請和釋放內存,無法強制要求其做自定義類型對象構造和析構工作。
g.重載
C++允許重載new/delete操作符,特別的,布局new的就不需要為對象分配內存,而是指定了一個地址作為內存起始區域,new在這段內存上為對象調用構造函數完成初始化工作,並返回此地址。而malloc不允許重載。
h.內存區域
new操作符從自由存儲區(free store)上為對象動態分配內存空間,而malloc函數從堆上動態分配內存。自由存儲區是C++基於new操作符的一個抽象概念,凡是通過new操作符進行內存申請,該內存即為自由存儲區。而堆是操作系統中的術語,是操作系統所維護的一塊特殊內存,用於程序的內存動態分配,C語言使用malloc從堆上分配內存,使用free釋放已分配的對應內存。自由存儲區不等於堆,如上所述,布局new就可以不位於堆中。
PS:
在C++中,內存區分為5個區,分別是堆、棧、自由存儲區、全局/靜態存儲區、常量存儲區;
在C中,C內存區分為堆、棧、全局/靜態存儲區、常量存儲區;
參考資料
《C和指針》,Kenneth A.Reek,人民郵電出版社
《C++ PRIMER》Stanley B.Lippman等,人民郵電出版社
相關鏈接
http://blog.csdn.net/nie19940803/article/details/76358673