new / delete与malloc / free的异同及实现原理
文章目錄
- 前言
- 一、new和delete是如何實現的?
- 二、new/delete和malloc/free的區別
- 三、delete p、delete [] p、allocator都有什么作用?
- 四、delete和delete[]區別?
- 五、malloc申請的存儲空間能用delete釋放嗎
- 六、malloc與free的實現原理?
- malloc函數
- calloc函數
- realloc函數
- 總結
前言
早餐店的老板問我要點什么,我說我要肆意妄為,志得意滿,要梨花帶雨和人見人愛,開個玩笑,我已經長大了,我要兩根油條和一份豆漿。
一、new和delete是如何實現的?
new的實現過程是:
1、new簡單類型直接調用operator new分配內存;
2、對于復雜結構:首先調用名為operator new的標準庫函數,分配內存,接下來調用該類型對象的構造函數,最后返回指向新分配并構造后的對象的指針
3、對于簡單類型,new[]計算好大小后調用operator new;
4、對于復雜數據結構,new[]先調用operator new[]分配內存,然后在p的前四個字節寫入數組大小n,然后調用n次構造函數,針對復雜類型,new[]會額外存儲數組大小;
delete的實現過程:
1、delete簡單數據類型默認只是調用free函數;復雜數據類型先調用析構函數再調用operator delete 釋放該對象所占內存;
2、針對簡單類型,delete和delete[]等同。假設指針p指向new[]分配的內存。因為要4字節存儲數組大小,實際分配的內存地址為[p-4],系統記錄的也是這個地址。delete[]實際釋放的就是p-4指向的內存。而delete會直接釋放p指向的內存,這個內存根本沒有被系統記錄,所以會崩潰。
3、需要在new []一個對象數組時,需要保存數組的維度,C++的做法是在分配數組空間時多分配了4個字節的大小,專門保存數組的大小,在delete []時就可以取出這個保存的數,就知道了需要調用析構函數多少次了。
二、new/delete和malloc/free的區別
1、new/delete是C++運算符,支持重載,malloc/free是C/C++語言標準庫函數,支持覆蓋。
2、new自動計算要分配的空間大小,malloc需手工計算。
3、new是類型安全的,malloc不是。例如:
int*p=new float[2];//編譯錯誤 int*p=(int*)malloc(2*sizeof(double));//編譯無錯誤4、new調用名為operator new的標準庫函數分配足夠空間并調用相關對象的構造函數,delete對指針所指對象運行適當的析構函數;然后通過調用名為operator delete的標準庫函數釋放該對象所用內存。后者均沒有相關調用。
5、new是封裝了malloc,直接free不會報錯,但是這只是釋放內存,而不會析構對象。
6、malloc、free需要庫文件支持,new/delete需要編譯器支持。
7、malloc和free返回的是void類型指針(必須進行類型轉換),new和delete返回的是具體類型指針。
8、new內存分配失敗時,會拋出bac_alloc異常。malloc分配內存失敗時返回NULL。
三、delete p、delete [] p、allocator都有什么作用?
1、動態數組管理new一個數組時,[]中必須是一個整數,但是不一定是常量整數,普通數組必須是一個常量整數;
2、new動態數組返回的并不是數組類型,而是一個元素類型的指針;
3、delete[]時,數組中的元素按逆序的順序進行銷毀;
4、new在內存分配上面有一些局限性,new的機制是將內存分配和對象構造組合在一起,同樣的,delete也是將對象析構和內存釋放組合在一起的。allocator將這兩部分分開進行,allocator申請一部分內存,不進行初始化對象,只有當需要的時候才進行初始化操作。
四、delete和delete[]區別?
delete只會調用一次析構函數。
delete[]會調用數組中每個元素的析構函數。
五、malloc申請的存儲空間能用delete釋放嗎
1、不能,malloc /free主要為了兼容C,new和delete完全可以取代malloc /free的。malloc /free的操作對象都是必須明確大小的,而且不能用在動態類上。
2、new和delete會自動進行類型檢查和大小,malloc/free不能執行構造函數與析構函數,所以動態對象它是不行的。
3、當然從理論上說使用malloc申請的內存是可以通過delete釋放的。不過一般不這樣寫的。而且也不能保證每個C++程序運行時都能正常。
六、malloc與free的實現原理?
1、在標準C庫中,提供了malloc/free函數分配釋放內存,這兩個函數底層是由brk、mmap、,munmap這些系統調用實現的;
2、brk是將數據段(.data)的最高地址指針_edata往高地址推,mmap是在進程的虛擬地址空間中(堆和棧中間,稱為文件映射區域的地方)找一塊空閑的虛擬內存。這兩種方式分配的都是虛擬內存,沒有分配物理內存。在第一次訪問已分配的虛擬地址空間的時候,發生缺頁中斷,操作系統負責分配物理內存,然后建立虛擬內存和物理內存之間的映射關系;
3、malloc小于128k的內存,使用brk分配內存,將_edata往高地址推;malloc大于128k的內存,使用mmap分配內存,在堆和棧之間找一塊空閑內存分配;brk分配的內存需要等到高地址內存釋放以后才能釋放,而mmap分配的內存可以單獨釋放。當最高地址空間的空閑內存超過128K(可由M_TRIM_THRESHOLD選項調節)時,執行內存緊縮操作(trim)。在上一個步驟free的時候,發現最高地址空閑內存超過128K,于是內存緊縮。
4、malloc是從堆里面申請內存,也就是說函數返回的指針是指向堆里面的一塊內存。操作系統中有一個記錄空閑內存地址的鏈表。當操作系統收到程序的申請時,就會遍歷該鏈表,然后就尋找第一個空間大于所申請空間的堆結點,然后就將該結點從空閑結點鏈表中刪除,并將該結點的空間分配給程序。
malloc函數
void*malloc(unsignedintnum_size);
intp=malloc(20sizeof(int));申請20個int類型的空間;
calloc函數
void*calloc(size_tn,size_tsize);
int*p=calloc(20,sizeof(int));
省去了人為空間計算;malloc申請的空間的值是隨機初始化的,calloc申請的空間的值是初始化為0的。
realloc函數
voidrealloc(void*p,size_tnew_size);
給動態分配的空間分配額外的空間,用于擴充容量。
總結
new / delete與malloc / free都可用于內存的動態申請和釋放。但要注意他們之間的差異。
總結
以上是生活随笔為你收集整理的new / delete与malloc / free的异同及实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux多进程知识汇总
- 下一篇: 析构函数为什么写成虚函数?