【C/C++】淺析new/delete和malloc/free之間的關係
阿新 • • 發佈:2019-02-01
- 程式的記憶體分配
- new/delete用法
- malloc/free用法
- new和malloc區別
- 程式的記憶體分配
一個由C/C++編譯的程式佔用的記憶體分為以下幾個部分:
1、棧區(stack)——由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。
2、堆區(heap)—— 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由OS回收 。注意它與資料結構中的堆是兩回事,分配方式倒是類似於連結串列。
3、全域性區(靜態區)(static)——全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域, 未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。 程式結束後由系統釋放。
4、文字常量區 —— 常量字串就是放在這裡的。 程式結束後由系統釋放 。
5、程式程式碼區 —— 存放函式體的二進位制程式碼。
ps:
在C++中,記憶體區分為5個區,分別是堆、棧、自由儲存區、全域性/靜態儲存區、常量儲存區;new是在自由儲存區開闢記憶體。
在C中,記憶體區分為堆、棧、全域性/靜態儲存區、常量儲存區;malloc是在堆上開闢記憶體。
自由儲存區和堆仍有疑問,先繼續向後學習,這裡有個參考。
C++自由儲存區是否等價於堆?
- new/delete的用法
C++關鍵字,C++中使用
int *p1 = new int;//建立一個整形指標,返回一個指向該物件的地址
int *p2 = new int();//同上,並且將指標p2指向的地址的值初始化為0
int *p3 = new int(1024);//同上,並且將指標p3指向的地址的值初始化為1024
delete p1,p2,p3;//釋放指標pi(i=1,2,3)指向的int型物件所佔的空間
//此時pi儘管沒有意義,但依然存放了他所指向物件的地址,
//而pi所指向記憶體已被釋放,不再有效
//釋放後,對其置空,清除表明指標不指向任何物件
p1 = NULL;
p2 = NULL;
p3 = NULL;
動態開闢陣列
int *p = new int[];//開闢一個數組。令p指向該陣列
int *p = new int[length];//開闢一個長度為length的陣列,未初始化。
int *p = new int[length]();//開闢一個長度為length的陣列,且初始化為0。
//動態開闢的陣列釋放與一般物件的釋放不一樣
delete[] p;//釋放p所指向的陣列
p = NULL;
- malloc/free
兩個函式在標頭檔案stdlib.h中,其原型如下:
void *malloc(size_t size);
void free(void *pointer);
因為malloc()函式的返回值型別為void *,所以需要在函式前面進行相應的強制型別轉換。
int *p = (int *)malloc(100);//開闢大小為100位元組的記憶體
int *p = (int *)malloc(25 * sizeof(int));//開闢25個int大小的記憶體
//驗證記憶體是否分配成功
if (NULL == p)
printf("Out of memory!\n");
free(p);//釋放記憶體
- new和malloc的區別
new | malloc | |
---|---|---|
屬性 | new/delete是C++關鍵字,需要編譯器支援 | malloc/free是庫函式,需要標頭檔案支援 |
引數 | 無須指定記憶體大小,編譯器會根據型別自行計算 | 顯式指出記憶體大小 |
返回型別 | 記憶體分配成功時,返回物件型別的指標,型別嚴格與物件匹配,無須進行型別轉換,故new是符合型別安全性的操作符 | 記憶體分配成功返回void * ,需要通過強制型別轉換將void*指標轉換成需要的型別 |
分配失敗 | 丟擲bac_alloc異常 | 返回NULL |
實現原理 | 過載new/delete運算子,構造/解構函式 | malloc/free庫函式,開闢/釋放空間 |