1. 程式人生 > >1:總結並剖析malloc/free和new/delete之間關係和差異。 2:剖析new/delete、new[]/delete[]到底做了些什麼事情。 3:實現NEW_ARRAY/DE

1:總結並剖析malloc/free和new/delete之間關係和差異。 2:剖析new/delete、new[]/delete[]到底做了些什麼事情。 3:實現NEW_ARRAY/DE

1:總結並剖析malloc/free和new/delete之間關係和差異。

2:剖析new/delete、new[]/delete[]到底做了些什麼事情。

3:實現NEW_ARRAY/DELETE_ARRAY巨集,模擬new[]/delete[]申請和釋放陣列。

malloc/free和new/delete之間關係和差異

首先先介紹一下malloc/free函式和new/delete操作符:

malloc/freenew/delete:

一.差異

(1)void *malloc(long NumBytes):該函式分配了NumBytes個位元組,並返回了指向這塊記憶體的指標。如果分配失敗,則返回一個空指標(NULL)。
void free(void *FirstByte): 該函式是將之前用malloc分配的空間還給程式或者是作業系統,也就是釋放了這塊記憶體,讓它重新得到自由。
new/delete都是操作符。

(2)new能夠自動計算需要分配的記憶體空間,而malloc需要手工計算位元組數。例如,int* p1=new int[2] , int* p2=malloc(2*sizeof(int))。

(3)new/delete直接帶具體型別的指標,malloc/free返回void型別的指標,接收指標的時候要強制型別轉換。

(4)new是型別安全的,而malloc不是。例如,int* p=new float[2],編譯時就會報錯;而int* p=malloc(2*sizeof(float)),編譯時編譯器就無法指出錯誤來。

(5)new一般由兩步構成,分別是new操作和構造。new操作對應於malloc,但new操作可以過載,可以自定義記憶體分配策略,不做記憶體分配,甚至分配到費記憶體裝置上,而malloc不可以。

(6)new是分配記憶體和初始化,因此將呼叫建構函式,而malloc不能;delete將呼叫解構函式,而free不能。

(7)malloc/free需要庫檔案stdlib.h支援,new/delete則不需要庫檔案支援。

注意

此外,需要注意的是:有記憶體的申請,就必需要有記憶體的釋放,否則就會出現記憶體洩露的問題,故new/delete、malloc/free必需配對使用。而且,delete或free被呼叫後,記憶體不會立即回收,指標也不會指向空,delete或free僅僅是告訴作業系統,這一塊記憶體被釋放了,可以被用做其它用途。由於沒有重新對這塊記憶體進行寫操作,所以記憶體中的變數數值並沒有發生變化,因此,釋放完記憶體後,應該將指標指向置為NULL,防止出現野指標。

二.剖析

(1)new/delete

new做了兩件事:1)呼叫operator new 分配空間;2)呼叫建構函式初始化物件.

delete做了兩件事:1)呼叫解構函式清理物件;2)呼叫operator delete 釋放空間.

(2)new[ ]/delete[ ]

new[ ]做了兩件事:1)呼叫operator new分配空間;2)呼叫N次建構函式分別對每個物件進行初始化.

delete[ ]做了兩件事:1)呼叫N次解構函式分別對每個物件進行清理;2)呼叫operator delete 釋放空間.

特別的:

int* p = new AA[3];
實際上在呼叫建構函式時(自己定義的類),會在p前面4個位元組(一個int)用來儲存陣列成員個數,用來確定具體構造幾次和析構幾次。
Alt text

三.實現NEW_ARRAY/DELETE_ARRAY巨集,模擬new[]/delete[]申請和釋放陣列。

 #define NEW_ARRAY(PTR,TYPE,N)      \
do{
PTR = (TYPE*)operator new(sizeof(TYPE)*N + 4); \
(*(int*)PTR) = N;                           \
PTR = (TYPE*)((char*)PTR + 4);                \
for (size_t i = 0; i < N; i++)                \
    new(PTR + i)TYPE;                         \
} while (false);
#define DELETE_ARRAY(PTR,TYPE)      \
do{
for (size_t i = 0; i < N; i++)  \
    PTR[i].~TYPE();           \
    PTR = (TYPE*)((char*)PTR - 4);  \
    operator delete(PTR);         \
} while (false);