1. delete 用於釋放 new 分配的空間,free 有用釋放 malloc 分配的空間
2. delete [] 用於釋放 new [] 分配的空間
3. delete 釋放空間的時候會調用 相應對象的析構函數
順便說一下new在分配空間的時候同時會調用對象的構造函數,對對象進行初始化,使用malloc則只是分配內存
4. 調用free 之前需要檢查 需要釋放的指針是否為空,使用delete 釋放內存則不需要檢查指針是否為NULL
5. free 和 delete 不能混用,也就是說new 分配的內存空間最好不要使用使用free 來釋放,malloc 分配的空間也不要使用 delete來釋放
舉個例子,<string.h>里通常有個strdup函數,它得到一個char*字符串然后返回其拷貝:
char * strdup(const char *ps); // 返回ps所指的拷貝
在有些地方,c和c++用的是同一個strdup版本,所以函數內部是用malloc分配內存。這樣的話,一些不知情的c++程序員會在調用strdup后忽視了必須對 strdup返回的指針進行free操作。為了防止這一情況,有些地方會專門為c++重寫strdup,並在函數內部調用了new,這就要求其調用者記得最后delete。你可以想象,這會導致多么嚴重的移植性問題,因為代碼中strdup以不同的形式在不同的地方之間顛來倒去。
補充一個問題,free和delete 是如何知道需要釋放的內存塊的大小的?
在調用malloc或new 分配內存空間的時候,實際分配的空間會比程序員申請的空間要大。實際分配的內存空間前面有一部分空間用於保存所分配內存的大小,校驗和等信息。當分配函數返回時,將會返回實際可操作的地址(也就是實際分配空間加上前面用於記錄分配信息的空間之后的地址)。下面舉個例子,例子通過破壞 new 返回地址的前面四個字節的數據導致內存空間釋放出問題。如果不破壞前面的數據則不會出現內存不能釋放的情況。
#include <stdio.h> #include <new> #include <iostream> #include <stdlib.h> #include <string.h> int main() { int *p = NULL,*p1=NULL; int i; //p = (int *) malloc(10 * sizeof(int)); p = new int[10]; memset(p,0,sizeof(int) * 10); for(i=0;i<10;i++) printf("P:%d\t",p[i]); printf("addr p: %x\n",p); *(p-1) = 2; //如果不注釋掉這一行則程序運行不正確 *(p+11) = 3; printf("addr before p: %x\n",p+11); printf("%x %x\n",*(p-1),*(p+11)); //free(p); delete [] p; printf("free successfully! \n"); return 0; }
當注釋了*(p-1) = 2之后運行結果為:
當不注釋*(p-1) =2 這一行時,結果為: