溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何理解C++的內(nèi)存管理

發(fā)布時(shí)間:2021-09-24 17:28:31 來源:億速云 閱讀:129 作者:柒染 欄目:開發(fā)技術(shù)

今天就跟大家聊聊有關(guān)如何理解C++的內(nèi)存管理,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

    一、C/C++內(nèi)存分布

    • 棧又叫堆棧,非靜態(tài)局部變量/函數(shù)參數(shù)/返回值等等,棧是向下增長(zhǎng)的。

    • 內(nèi)存映射段是高效的I/O映射方式,用于裝載一個(gè)共享的動(dòng)態(tài)內(nèi)存庫。用戶可使用系統(tǒng)接口創(chuàng)建共享共享內(nèi)存,做進(jìn)程間通信。

    • 堆用于程序運(yùn)行時(shí)動(dòng)態(tài)內(nèi)存分配,堆是可以向上增長(zhǎng)的。

    • 數(shù)據(jù)段–存儲(chǔ)全局?jǐn)?shù)據(jù)和靜態(tài)數(shù)據(jù)。

    • 代碼段–可執(zhí)行的代碼/只讀常量。

    如何理解C++的內(nèi)存管理

    二、C語言中動(dòng)態(tài)內(nèi)存管理方式:

    1、malloc/calloc/realloc區(qū)別:

    共同點(diǎn):

    • 都是C語言中用來進(jìn)行動(dòng)態(tài)內(nèi)存申請(qǐng)的庫函數(shù),申請(qǐng)的空間都在堆上,用完之后必須使用free來進(jìn)行釋放

    • 返回值類型都是void*在接受返回的地址時(shí)必須要進(jìn)行強(qiáng)轉(zhuǎn)

    • 如果申請(qǐng)空間成功:返回的是空間的首地址,如果失敗返回的是NULL

    不同點(diǎn):

    • malloc:返回值類型void*

    在接受返回的空間地址時(shí)必須要進(jìn)行強(qiáng)轉(zhuǎn)

    成功:空間首地址 失敗:NULL

    參數(shù):申請(qǐng)的空間所占總的字節(jié)數(shù)

    申請(qǐng)的空間在堆上,使用完成后必須要使用free來進(jìn)行釋放

    • calloc:返回值一致

    參數(shù)列表:參數(shù)一表示元素的個(gè)數(shù);參數(shù)二表示單個(gè)類型的字節(jié)數(shù)

    功能:與malloc基本相同,但是calloc會(huì)對(duì)其申請(qǐng)的空間進(jìn)行初始化

    • realloc(void* p, size_t size):將p所指向空間的大小調(diào)整到size字節(jié)

    p指向的是NULL:該函數(shù)的類似malloc

    假設(shè):p所指向的空間總共占o(jì)ld個(gè)字節(jié)

    size <= old:將p所指向的空間縮小到size個(gè)字節(jié)---->直接返回值p所指向空間的首地址

    size > old:將p所指向的空間擴(kuò)增到size個(gè)字節(jié)

    大一點(diǎn):返回原空間的首地址

    大的多的多:申請(qǐng)新空間;將舊空間中元素拷貝到新空間;釋放舊空間;返回新空間的首地址

    三、C++中動(dòng)態(tài)內(nèi)存管理:new/delete

    C++為什么要搞一套動(dòng)態(tài)內(nèi)存管理?

    首先:C語言中的動(dòng)態(tài)內(nèi)存管理方式在C++中仍然可以使用

    原因:

    1、C語言中的方式比較麻煩—需要用戶手動(dòng)算字節(jié)數(shù),需要對(duì)返回結(jié)果強(qiáng)轉(zhuǎn),需要判空,需要包含頭文件

    2、malloc、free:不會(huì)調(diào)用構(gòu)造函數(shù)/析構(gòu)函數(shù);new、delete:在進(jìn)行空間申請(qǐng)和釋放時(shí)是會(huì)調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的

    如何理解C++的內(nèi)存管理

    // C++中動(dòng)態(tài)內(nèi)存管理方式:new/delete----申請(qǐng)單個(gè)類型的空間
    // new[]/delete[]-----申請(qǐng)釋放一段連續(xù)的空間
    //注意:1、new/delete不是函數(shù),是C++中的關(guān)鍵字||操作符
    //		2、new的空間必須要有delete釋放  new[]必須使用delete[]釋放
    class Test
    {
    public:
    	Test()
    		:_t(10)
    	{
    		cout << "Test():" << this << endl;
    	}
    	~Test()
    	{
    		cout << "~Test():" << this << endl;
    	}
    	int _t;
    };
    //new/delete和new[]/delete[]使用說明
    void Test1()
    {
    	int* p1 = new int;
    	int* p2 = new int(100);
    	int* p3 = new int[10];
    	int* p4 = new int[10]{ 1,2,3,4,5,6,7,8,9,0 };
    	delete p1;
    	delete p2;
    	delete[] p3;
    	delete[] p4;
    }
    void Test2()
    {
    	//malloc并不是創(chuàng)建了一個(gè)Test類型的對(duì)象,只是在堆上申請(qǐng)了一塊與Test類型大小相同的一塊空間
    	//因?yàn)椋簃alloc不調(diào)用構(gòu)造函數(shù)
    	Test* p1 = (Test*)malloc(sizeof(Test));//malloc不會(huì)調(diào)用構(gòu)造函數(shù)
    	if (nullptr == p1)
    		return;
    	//真正創(chuàng)建了一個(gè)對(duì)象,該對(duì)象的空間在堆上
    	Test* p2 = new Test;//new在申請(qǐng)空間期間會(huì)調(diào)用構(gòu)造函數(shù)
    	free(p1);//:在釋放空間期間,不會(huì)調(diào)用析構(gòu)函數(shù)
    	delete p2;//:在釋放空間期間,會(huì)調(diào)用對(duì)象的析構(gòu)函數(shù)
    }
    /*
    在C++中,如果想要在堆上申請(qǐng)空間:
    1、采用C語言中的malloc、calloc、realloc,但是并不能申請(qǐng)對(duì)象的空間
    2、采用new/new[]---可以調(diào)用構(gòu)造函數(shù),注意:如果使用new[]申請(qǐng)連續(xù)的空間是,該類必須提供無參或全缺省的構(gòu)造函數(shù)
    3、malloc/free,new/delete,new[]/delete[]必須成對(duì)使用,否則會(huì)內(nèi)存泄漏或者代碼崩潰
    */

    注意:申請(qǐng)和釋放單個(gè)元素的空間,使用new和delete操作符,申請(qǐng)和釋放連續(xù)的空間,使用new[]和delete[]

    四、實(shí)現(xiàn)原理

    new的原理

    1、調(diào)用operator new函數(shù)申請(qǐng)空間

    2、在申請(qǐng)的空間上執(zhí)行構(gòu)造函數(shù),完成對(duì)象的構(gòu)造

    delete的原理

    1、在空間上執(zhí)行析構(gòu)函數(shù),完成對(duì)象中資源的清理工作

    2、 調(diào)用operator delete函數(shù)釋放對(duì)象的空間

    new T[N]的原理

    1、調(diào)用operator new[]函數(shù),在operator new[]中實(shí)際調(diào)用operator new函數(shù)完成N個(gè)對(duì)象空間的申
    請(qǐng)

    2、在申請(qǐng)的空間上執(zhí)行N次構(gòu)造函數(shù)

    delete[]的原理

    1、 在釋放的對(duì)象空間上執(zhí)行N次析構(gòu)函數(shù),完成N個(gè)對(duì)象中資源的清理

    2、調(diào)用operator delete[]釋放空間,實(shí)際在operator delete[]中調(diào)用operator delete來釋放空間

    五、面試常問問題

    1、malloc/free和new/delete的區(qū)別

    共同點(diǎn)是

    都是從堆上申請(qǐng)空間,并且需要用戶手動(dòng)釋放。

    不同的地方是:

    • malloc和free是函數(shù),new和delete是操作符

    • malloc申請(qǐng)的空間不會(huì)初始化,new可以初始化

    • malloc申請(qǐng)空間時(shí),需要手動(dòng)計(jì)算空間大小并傳遞,new只需在其后跟上空間的類型即可

    • malloc的返回值為void*, 在使用時(shí)必須強(qiáng)轉(zhuǎn),new不需要,因?yàn)閚ew后跟的是空間的類型

    • malloc申請(qǐng)空間失敗時(shí),返回的是NULL,因此使用時(shí)必須判空,new不需要,但是new需要捕獲異常

    • 申請(qǐng)自定義類型對(duì)象時(shí),malloc/free只會(huì)開辟空間,不會(huì)調(diào)用構(gòu)造函數(shù)與析構(gòu)函數(shù),而new在申請(qǐng)空間后會(huì)調(diào)用構(gòu)造函數(shù)完成對(duì)象的初始化,delete在釋放空間前會(huì)調(diào)用析構(gòu)函數(shù)完成空間中資源的清理

    2、內(nèi)存泄漏

    什么是內(nèi)存泄漏:內(nèi)存泄漏指因?yàn)槭韬龌蝈e(cuò)誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存的情況。內(nèi)存泄漏并不是指內(nèi)存在物理上的消失,而是應(yīng)用程序分配某段內(nèi)存后,因?yàn)樵O(shè)計(jì)錯(cuò)誤,失去了對(duì)該段內(nèi)存的控制,因而造成了內(nèi)存的浪費(fèi)。

    內(nèi)存泄漏的危害:長(zhǎng)期運(yùn)行的程序出現(xiàn)內(nèi)存泄漏,影響很大,如操作系統(tǒng)、后臺(tái)服務(wù)等等,出現(xiàn)內(nèi)存泄漏會(huì)導(dǎo)致響應(yīng)越來越慢,最終卡死

    內(nèi)存泄漏分類(了解)

    C/C++程序中一般我們關(guān)心兩種方面的內(nèi)存泄漏:

    1、堆內(nèi)存泄漏(Heap leak)

    堆內(nèi)存指的是程序執(zhí)行中依據(jù)須要分配通過malloc / calloc / realloc / new等從堆中分配的一塊內(nèi)存,用完后必須通過調(diào)用相應(yīng)的 free或者delete 刪掉。假設(shè)程序的設(shè)計(jì)錯(cuò)誤導(dǎo)致這部分內(nèi)存沒有被釋放,那么以后這部分空間將無法再被使用,就會(huì)產(chǎn)生Heap Leak。

    2、系統(tǒng)資源泄漏

    指程序使用系統(tǒng)分配的資源,比方套接字、文件描述符、管道等沒有使用對(duì)應(yīng)的函數(shù)釋放掉,導(dǎo)致系統(tǒng)資源的浪費(fèi),嚴(yán)重可導(dǎo)致系統(tǒng)效能減少,系統(tǒng)執(zhí)行不穩(wěn)定。

    如何避免內(nèi)存泄漏

    1、工程前期良好的設(shè)計(jì)規(guī)范,養(yǎng)成良好的編碼規(guī)范,申請(qǐng)的內(nèi)存空間記著匹配的去釋放。ps:這個(gè)理想狀態(tài)。但是如果碰上異常時(shí),就算注意釋放了,還是可能會(huì)出問題。需要下一條智能指針來管理才有保證。

    2、 采用RAII思想或者智能指針來管理資源。

    3、有些公司內(nèi)部規(guī)范使用內(nèi)部實(shí)現(xiàn)的私有內(nèi)存管理庫。這套庫自帶內(nèi)存泄漏檢測(cè)的功能選項(xiàng)。

    4、出問題了使用內(nèi)存泄漏工具檢測(cè)。ps:不過很多工具都不夠靠譜,或者收費(fèi)昂貴。

    解決方案:

    1、事前預(yù)防型。如智能指針等。

    2、事后查錯(cuò)型。如泄漏檢測(cè)工具。

    看完上述內(nèi)容,你們對(duì)如何理解C++的內(nèi)存管理有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    c++
    AI