1. 程式人生 > >【C/C++】淺析new/delete和malloc/free之間的關係

【C/C++】淺析new/delete和malloc/free之間的關係

  • 程式的記憶體分配
  • 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庫函式,開闢/釋放空間