每一個程序在執行時都會佔用一塊可用的內存空間,用於存放動態分配的對象,此內存空間稱爲自由存儲區或堆。數組
以下幾行代碼:安全
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,這樣就清楚的代表指針再也不指向任何對象。 spa
p=NULL;
值得注意的是當執行下列表達式:操作系統
int pi=&i; delete pi;
編譯器通常不會報錯,由於編譯器一般不能判定一個指針指向什麼類型的對象,因此儘管這個語句是錯誤的,但在大多數編譯器上仍然能經過。.net
C++中容許動態建立const對象:指針
const int *pi=new const int(1024);
動態建立的const對象必須進行初始化,而且進行初始化後的值不能再改變。code
當建立一個動態數組對象和進行內存釋放時,執行如下語句:對象
int *pi=new int[]; //指針pi所指向的數組未初始化 int *pi=new int[n]; //指針pi指向長度爲n的數組,未初始化 int *pi=new int[](); //指針pi所指向的地址初始化爲0 delete [] pi; //回收pi所指向的數組
兩個函數的原型以下,他們都在頭文件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函數用於修改一個原先已經分配的內存塊的大小。可使一塊內存擴大或縮小,若是擴大內存,則原來的內存塊保持不變,在內存尾部增長新的內存塊,切不進行初始化。若是縮小內存,則原來內存塊從尾部進行刪減。若是原先的內存塊沒法擴充,則新開闢一塊內存,並複製原先的內存的內容,原先內存塊失效沒法再進行訪問。
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等,人民郵電出版社
相關連接