這篇文章主要為大家展示了“C++中動態內存管理的示例分析”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“C++中動態內存管理的示例分析”這篇文章吧。
計算機物理內存的大小是固定的,在32位系統上,地址空間可達4G(2^32),這4G按照3:1的比例分配給用戶進程和內核。程序地址空間的構成:從上往下依次是:內核空間、棧區、共享區、堆區、未初始化數據區、初始化數據區、代碼區。而動態內存管理所申請的空間都是在堆區,在堆區動態開辟的空間都需要我們手動去釋放它,否則會造成內存泄漏。
內核空間:操作系統相關代碼
棧區:從高地址向低地址增長
共享區:加載動態庫,共享內存
堆區:從低地址向高地址增長
未初始化全局數據區
已初始化全局數據區
代碼區:可執行代碼及只讀常量

void* malloc(size_t size);
malloc()函數只有一個參數,即要分配的內存空間的大小。
如果開辟成功,則返回一個指向開辟好空間的指針,如果開辟失敗,則返回一個空指針,因此每次申請完空間都需要判空。
malloc()函數返回值的類型是void*,在使用時需要自己強制轉換。
void* calloc (size_t num, size_t size);
calloc()函數有兩個參數,分別是元素的數目和每個元素的大小,這兩個參數的乘積就是要分配的內存空間的大小。
malloc申請后空間的值是隨機的,并沒有進行初始化,而calloc在申請后,對空間逐一進行初始化,并設置值為0;
calloc由于給每一個空間都要初始化,所以效率必然比malloc低。
void* realloc (void* ptr, size_t size);
realloc()函數就實現對 動態開辟 內存大小的調整。
realloc()函數包含兩個參數,分別是要調整的內存地址和調整的新大小。
realloc在調整內存空間時有兩種情況:
情況1:原有空間之后有足夠大的空間,我們就把需要擴展的內存直接放到原來空間的后面,原來空間的數據不發生變化。
情況2:原有空間之后沒有足夠大的空間,那就在堆上找一個合適大小的連續空間,將原來內存中的數據移動到新空間,然后將這個新空間的地址返回。
void* free(void* ptr);
free函數用來釋放動態開辟的函數。
C++作為一門在C語言的基礎上發展而來的語言,它本身是完全兼容C語言的,也就是說,C語言的動態內存管理方式在C++中依舊可以正常使用。那它為什么還要設計一套屬于自己的動態內存管理方式呢?
在C++中,使用malloc/free申請或釋放內置類型的空間并沒有任何問題,但我們知道C++引入了類和對象的概念,而這一點帶來的影響就是并不能使用malloc從堆上為對象申請空間,因為malloc并不會去主動的去調用構造函數,這意味著其并不能成為真正的對象。所以如果使用malloc只是申請了一段和對象同樣大小的空間而言,并非對象。同理使用free并不能釋放堆上對象的空間,因為free并不會調用析構函數去釋放對象中的資源。
而且C++所提供的動態內存管理方式使用起來更加方便、簡單,對用戶更加友好,并且不用去擔心空間可能會申請失敗的情況。
new操作符的格式:
new 類型; new 類型(初值); new 類型[];
delete操作符的格式:
delete 指針變量; delete[] 指針變量;
int main(){
int *p1 = new int; //動態申請一個int類型的空間
int *p2 = new int(10); //動態申請一個int類型的空間并初始化為10
int *p3 = new int[3]; //動態申請10個int類型的空間
//釋放申請的空間
delete p1;
delete p2;
delete[] p3;
return 0;
}//定義一個簡單的類
class Data{
public:
//構造函數
Data(int data = 0) : _data(data)
{
cout << "Data() :" << this << endl;
}
//析構函數
~Data()
{
cout << "~Data() : " << this << endl;
}
private:
int _data;
};
int main()
{
Data *d1 = new Data; //申請單個Data類型的對象
Data *d2 = new Data(10); //申請單個Data類型的對象并初始化
Data *d3 = new Data[5]; //申請5個Data類型的對象
//依次釋放申請的對象資源
delete d1;
delete d2;
delete[] d3;
//使用new/delete為類對象申請或釋放空間時會主動調用構造函數/析構函數完成對象的構造/資源的清理。
return 0;
}new 和 delete在堆上申請和釋放空間的時候,在底層實際上調用的是operator new和operator delete兩個全局函數。
而operator new和operator delete最終還是調用malloc和free來申請和釋放空間。



1)new/delete內置類型的原理
如果申請的是內置類型的空間,new和malloc,delete和free基本類似,不同的地方是:new/delete申請和釋放的是單個元素的空間,new[]和delete[]申請的是連續空間,而且new在申請空間失敗時會拋異常,malloc會返回NULL。也就是說使用new操作符不需要進行判空。
2)new/delete自定義類型的原理
new的原理
1.調用operator new函數申請空間
2.在申請的空間上執行構造函數,完成對象的構造
delete的原理
1.在空間上執行析構函數,完成對象中資源的清理工作
2.調用operator delete函數釋放對象的空間
new[]的原理
1.調用operator new[]函數,在operator new[]中實際調用operator new函數完成N個對象空間的申請
2.在申請的空間上執行N次構造函數
delete[]的原理
1.在釋放的對象空間上執行N次析構函數,完成N個對象中資源的清理
2.調用operator delete[]釋放空間,在operator delete[]中實際調用operator delete來釋放空間
都是從堆上申請空間,并且需要用戶手動釋放。
1.malloc和free是函數,new和delete是C++中的操作符
2.malloc申請的空間不會初始化,new可以初始化
3.malloc申請空間時,需要手動計算空間大小并傳遞,new只需在其后跟上類型即可
4.malloc的返回值為void * , 在使用時必須強轉,new不需要,因為new后跟的是空間的類型
5.malloc申請空間失敗時,返回的是NULL,因此使用時必須判空,new不需要,但是new需要捕獲異常
6.申請自定義類型對象時,malloc/free只會開辟空間,不會調用構造函數與析構函數,而new在申請空間后會調用構造函數完成對象的初始化,delete在釋放空間前會調用析構函數完成空間中資源的清理
內存泄漏是指你向系統申請分配內存進行使用(new/malloc),然后系統在堆內存中給這個對象申請一塊內存空間,但當我們使用完了卻沒有歸還給系統(delete),導致這個不使用的對象一直占據內存單元,造成系統將不能再把它分配給需要的程序。
一次內存泄漏的危害可以忽略不計,但是內存泄漏堆積則后果很嚴重,無論多少內存,遲早會被占完,造成內存泄漏。
以上是“C++中動態內存管理的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。