C++中的動態內存管理

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

相同點:

都可用於申請動態內存和釋放內存

不同點:

(1)操作對象不同
malloc/free是C++/c語言的標準庫函數,new/delete是c++的運算符,對於非內部數據類型的對象而言,只有malloc、free是無法滿足動態對象的要求的。因爲對象在創建的時候會自動調用構造函數,對象消亡時會自動調用析構函數。因爲malloc/free是庫函數而不是運算符,不在編譯器控制的範圍內,不能夠執行構造函和析構函數
(2)用法不同
函數malloc 的原型如下:
void*malloc(size_t size)
用malloc申請一塊長度爲n的整數類型的空間,代碼如下
int p = (int)malloc(sizeof(int)*n);
注意:
<1>. malloc返回值是void* ,歲喲調用時要進行顯示的類型轉換,講void* 轉換成所需要的類型
<2>.malloc函數本身並不識別要申請的內存是什麼類型,只關心內存的總字節數
函數free的原型:
void free(void* memblock)
爲什麼free函數不像malloc函數那樣複雜呢?這是因爲指針p 的類型以及他所指向的內存的容量都是事先知道的,free(p)纔可以正確的釋放p,如果p是NULL,free對p烏雲操作多少次都不會出現問題,而如果p不是NULL,那麼free進行兩次就會出現錯誤,就是已經釋放的空間連續釋放,就會出現問題
new、delete
運算符new 使用起來要比函數malloc 簡單得多,例如:
int p1 = (int )malloc(sizeof(int) * length);
int *p2 = new int[length];
這是因爲new 內置了sizeof、類型轉換和類型安全檢查功能。對於非內部數據類型的對象而言,new 在創建動態對象的同時完成了初始化工作。
delete是與new成對出現的,new/delete new[]/delete[] 注意一定要成對使用

1、本質區別
malloc/free是C/C++語言的標準庫函數,new/delete是C++的運算符。
對於用戶自定義的對象而言,用maloc/free無法滿足動態管理對象的要求。對象在創建的同時要自動執行構造函數,對象在消亡之前要自動執行析構函數。由於malloc/free是庫函數而不是運算符,不在編譯器控制權限之內,不能夠把執行構造函數和析構函數的任務強加於malloc/free。因此C++需要一個能完成動態內存分配和初始化工作的運算符new,以及一個能完成清理與釋放內存工作的運算符delete。
2、聯繫:
既然new/delete的功能完全覆蓋了malloc/free,爲什麼C++還保留malloc/free呢?因爲C++程序經常要調用C函數,而C程序只能用malloc/free管理動態內存。如果用free釋放“new創建的動態對象”,那麼該對象因無法執行析構函數而可能導致程序出錯。如果用delete釋放“malloc申請的動態內存”,理論上講程序不會出錯,但是該程序的可讀性很差。所以new/delete、malloc/free必須配對使用。

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

這裏寫圖片描述

這裏寫圖片描述
不管是new還是new[] 都調用了operator new函數,在operator new函數中,又調用了malloc函數。
當然new[] 調用了operator new[] 而operator new[] 又調用了operator new函數。
在底層實現中,new就是用malloc函數來開闢空間的。

實現NEW_ARRAY/DELETE_ARRAY宏,模擬new[]/delete[]申請和釋放數組。

#define NEW_ARRAY(PTR,TYPE,N)\
 do                          \
{PTR = (TYPE*)operator new(sizeof(TYPE)*N+4)\
    (*(int*)PTR) = N                        \ 
    for(size_t i = 0;i<N;i++)               \
    new (PTR+i)TYPE;                        \
}while(false);
//爲什麼在申請空間的時候要多申請四個字節呢?這是因爲需要用來記錄對象的個數,可以知道在析構的是後要調用幾次
//析構函數
#define DELETE_ARRAY(PTR,TYPE)      \
    do{int N = *((int*)PTR-1) //這裏取出保存的對象的個數   \
    for(size_t i=0;i<N;i++)         \
{PTR[i].~TYPE();                    \
PTR = (TYPE*)((char*)PTR-4);        \
    operator  delete(PTR); }         \ 
    }while(false);
//注意:在用宏實現的收,一定要加上續行符。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章