动态内存管理:malloc和free以及new和delete的联系与区别
動態內存管理:malloc和free以及new和delete的聯系與區別
文章目錄
- 動態內存管理:malloc和free以及new和delete的聯系與區別
- 一、 C/C++中程序內存區域劃分:
- 二、C語言中動態分配內存管理方式:
- 三、C++內存管理方式
- 四、malloc/free與new/delete的區別:
一、 C/C++中程序內存區域劃分:
1. 內核空間:Linux系統對自身進行了劃分,一部分核心軟件獨立于普通應用程序,運行在較高的特權級別上,它們駐留在被保護的內存空間上,擁有訪問硬件設備的所有權限,Linux將此稱為內核空間。
2. 棧:又叫堆棧,非靜態局部變量和函數參數及返回值都在棧上存儲,棧是重上往下增長的。
3. 內存映射段:是高效的I/O映射方式,用于裝載一個共享的動態內存庫,用戶可以使用系統接口創建共享共享內存,做進程間通信,
4. 堆:用于程序運行時動態分配內存,堆是從下往上增長的。
5. 數據段:存儲靜態數據和全局變量。
6. 代碼段:可執行時的代碼和只讀常量。
具體如下圖:
二、C語言中動態分配內存管理方式:
-
malloc:
-
原型:
- 作用:動態開辟byte_size個字節的內存空間,不進行初始化,返回指向此內存的指針,此指針所指數據類型沒有確定,需要強轉。
舉例:
int *p=(int *)malloc(5*sizeof(int));- 例解:動態開辟5*4=20個字節大小的空間,返回空間首地址指針并強轉為int *型后賦予指針變量p。
注意:malloc只開辟空間,不初始化,即只將此空間由未占用狀態變為已占用狀態,空間內存儲的具體數據未指定改變。函數返回值是空間首地址,上例中賦給了p變量。
-
calloc:
-
原型:void *calloc(int n,int type_byte_size);
-
作用:動態開辟n*type_byte_size個字節,將每個字節均初始化為ascii碼0,返回指向此內存的指針,此指針所指數據類型沒有確定,需要強轉。
舉例:int *p=(int *)calloc(5,sizeof(int));
例解:動態開辟5*4=20個字節大小的空間,其中每個字節均賦初值0,返回空間首地址指針并強轉為int *型后賦予指針變量p。
- 注意:calloc在malloc的基礎上將空間按字節初始化為ascii碼0,且其參數有兩個,兩參數之積為空間總字節數。
realloc:
原型:
void *realloc(void *p,int byte_size);- 作用:對空間進行調整,若p為空,則該函數與malloc相同
- 若p所指空間連續大小(單位字節)大于byte_size,則從首地址開始連續地擴充開辟p所指空間至byte_size字節,不對空間再次賦值,將空間地址指針返回;
- 若p所指空間連續大小小于byte_size,則新開辟byte_size字節大小的空間,將p指向的空間內的數據復制進新空間,之后釋放p所指空間(此時p為NULL),返回指向新空間的指針,此指針所指數據類型沒有確定,需要強轉。
舉例:
int *p=(int *)calloc(5,sizeof(int)); p =(int*)realloc(p,10*sizeof(int));-
例解:首句中p為5*4=20字節的空間指針并按字節初始化為ascii碼0,(int*)強轉后才限定了指向空間的每個元素為int型。
-
后句將p所指空間擴充為10*4=40字節的空間指針,未對其二次賦值,故此時p[0]~p[4]為0,p[5]~p[9]未初始化。
注意:realloc的第一個參數必須是動態開辟的地址,不能是靜態定義的數組的地址,結構體數組也不行。
- free:
- C 庫函數 *void free(voidptr)** 釋放之前調用 calloc、malloc 或 realloc所分配的內存空間 。
- ptr-- 指針指向一個要釋放內存的內存塊,該內存塊之前是通過調用 malloc、calloc 或 realloc 進行分配內存的。如果傳遞的參數是一個空指針,則不會執行任何動作。
- 該函數不返回任何值
下面的實例演示了 free() 函數的用法:
#include <stdio.h>int main() { char *str; /* 最初的內存分配 */ str = (char *) malloc(15); strcpy(str, "jikexueyuan"); printf("String = %s, Address = %un", str, str); /* 重新分配內存 */ str = (char *) realloc(str, 25); strcat(str, ".com"); printf("String = %s, Address = %un", str, str); /* 釋放已分配的內存 */ free(str); return(0);}讓我們編譯并運行上面的程序,這將產生以下結果:
String = jikexueyuan, Address = 355090448String = jikexueyuan.com, Address = 355090448三、C++內存管理方式
- new/delete操作內置類型:
注意:申請和釋放單個元素空間,使用new/delete操作符,申請和釋放連續元素空間,使用new[]/delete[]操作符。
- new/delete操作自定義類型:
注意:在申請自定義類型空間時,new會調用類的構造函數,delete會調用類的析構函數,malloc和free不會調用。
-
new和delete的實現原理:
-
a、如果申請的是內置空間:
-
那么new/delete,malloc/free就沒有太大區別。
-
不同的地方主要有如果malloc申請空間失敗,則會返回NULL,所以在用之前要進行判空處理。
-
而new操作符申請空間時,如果失敗,就會優先進行調整,若沒有調整操作,就會拋出異常。
-
b、如果申請的是自定義空間:
-
new的原理為:
-
首先調用operator new函數申請一個空間,而operator new函數則采用循環的方式,用malloc來進行申請空間
-
若申請空間失敗,就會優先進行調整操作,直到申請成功,若沒有調整操作,就會拋出異常。
-
注意此時并沒有申請成功,只是相當于申請了以個大小相同的空間而已,此時該對象是不完整的
-
所以最后進行的操作是在申請的空間上執行類的構造函數,完成對象的構造。
-
delete的原理為:
-
首先為了防止內存泄漏,在該空間上執行類的析構函數,完成對象資源清理工作,最后調用operator delete函數,釋放該對象的空間。
-
new[N]的原理為:
-
調用operator new[] 函數,而在operator new[]中實際調用operator new函數完成對N個對象空間的申請操作,最后在申請的空間上執行N次構造函數,完成對N個對象的申請。
-
delete[]原理為:
-
在申請的空間上執行N次析構函數,完成對N個對象的資源清理工作,最后在調用operator delete[] 函數,而在operator delete[]函數中實際調用operator delete函數完成對N個對象空間的釋放回收操作。
四、malloc/free與new/delete的區別:
| 是標準庫內的函數 | 是關鍵字,不是函數 |
| malloc申請的空間不會初始化 | new出來的空間可以初始化 |
| malloc申請空間時,需要手動計算申請空間的大小并傳遞 | new不需要,只需在后面跟空間的類型 |
| malloc的返回值為void*,所以在使用時要進行強轉操作 | new后跟的就是空間的類型 |
| malloc申請空間失敗會返回NULL,所以使用時需要判空 | new申請空間失敗會拋出異常 |
| 在申請自定義空間時,malloc/free只負責開辟空間,和釋放空間,不會調用構造函數和析構函數 | new會在申請空間后調用構造函數完成對象的初始化,delete會在釋放空間前調用析構函數完成資源清理工作。 |
總結
以上是生活随笔為你收集整理的动态内存管理:malloc和free以及new和delete的联系与区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C和C++中static的用法及友元
- 下一篇: 二叉树和栈的基本操作