C++內(nèi)存分布及用法
一、內(nèi)存基礎(chǔ)
1、內(nèi)存分布
通過下面一張圖看看C++的內(nèi)存分布:
棧區(qū):由編譯器自動分配與釋放,存放為程序運(yùn)行時函數(shù)分配的局部變量、函數(shù)參數(shù);棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配內(nèi)存的容量有限;
堆區(qū):由new
、malloc
分配的內(nèi)存塊,釋放由應(yīng)用程序控制,不需要編譯器釋放;如果程序員沒有對該內(nèi)存進(jìn)行釋放,程序結(jié)束后系統(tǒng)自動回收,堆的地方比棧大很多;
靜態(tài)區(qū):存放的是static
的靜態(tài)變量和一些全局變量,特點(diǎn)是只讀、大小固定;靜態(tài)變量和全局變量的存儲期是一起的,一旦靜態(tài)區(qū)的內(nèi)存被分配,要一直等到程序全部結(jié)束后才釋放;
2、棧區(qū)與堆區(qū)的區(qū)別
1、分配方式不同:棧區(qū)系統(tǒng)分配系統(tǒng)回收;堆區(qū)由程序員手動申請,需要求程序員自行回收,如果沒有回收,系統(tǒng)在程序結(jié)束后會進(jìn)行回收,這種情況會造成內(nèi)存泄漏;
2、生命周期不同:棧區(qū)生命周期是系統(tǒng)分配到系統(tǒng)回收,也就是在大括號內(nèi);堆區(qū)是從申請到釋放;
3、效率不同:主要原因是地址空間是否連續(xù),棧區(qū)地址空間是連續(xù)的,效率會高一些;堆區(qū)地址空間不連續(xù),需要遍歷鏈表才能找到最近的地址,效率會低一些;
4、內(nèi)存碎片:堆區(qū)容易產(chǎn)生內(nèi)存碎片,棧區(qū)不會;
5、生長方向不同:棧區(qū)申請空間的地址(表示地址的八個十六進(jìn)制數(shù))是從大到小的,堆區(qū)申請空間地址是從小到大的。棧區(qū)是先進(jìn)后出的原則,類比棧結(jié)構(gòu)的特點(diǎn);
- 棧區(qū)特點(diǎn):更好的局部性,對象自動銷毀;
- 堆區(qū)特點(diǎn):運(yùn)行期動態(tài)擴(kuò)展,需要顯示釋放;
注意點(diǎn):申請的空間是在堆區(qū),變量本身是在棧區(qū)!
二、內(nèi)存分配
1、內(nèi)存分配方式
可操作的內(nèi)存分配:
- 靜態(tài)存儲區(qū)分配:
static
靜態(tài)變量、全局變量; - 棧上分配:局部變量;
- 堆上分配:
new
、malloc
進(jìn)行內(nèi)存分配;
不可操作的內(nèi)存分配:
內(nèi)核區(qū)、代碼區(qū)、局部變量的分配也屬于系統(tǒng)分配;
2、new的用法
C++中通常使用new
、delete
來構(gòu)造和銷毀對象;
使用new創(chuàng)建對象,返回的是對象的首地址,需要用指針接收:
int *y = new int(2); std::cout << *y << std::endl;
對象的構(gòu)建和銷毀分為兩步:分配內(nèi)存、所分配內(nèi)存上構(gòu)造對象(銷毀與之類似);
new的幾種常見形式:
new int(2)
:構(gòu)造單一對象、new int[5]:構(gòu)造數(shù)組;nothrow new
:標(biāo)準(zhǔn)庫定義,解決內(nèi)存分配失敗異常的問題;placement new
:使用已經(jīng)創(chuàng)建的內(nèi)存,跳過分配內(nèi)存;new auto
;
3、delete用法
根據(jù)分配的是單一對象還是數(shù)組,采用相應(yīng)的方式銷毀;
int *y = new int[3]; delete[] y;
不能delete
一個非new返回的內(nèi)存(也就是棧內(nèi)存);delete nullptr
是可被允許的;
同一塊內(nèi)存不能delete
多次;
4、new與malloc的區(qū)別
new
不需要指定分配多大,malloc
使用的時候必須指定大??;new
的底層實(shí)現(xiàn)就是malloc
,兩者都必須釋放內(nèi)存,不否則容易造成野指針或內(nèi)存泄漏。需要注意一點(diǎn),釋放內(nèi)存后需設(shè)置相關(guān)指針為空指針;
總結(jié):
- 屬性:
new
為關(guān)鍵字(編譯器),malloc是庫函數(shù)(需引入頭文件); - 參數(shù):
new
無需指定大小,malloc需指定大??; - 返回類型:new返回對象指針,
malloc
返回void*; - 對于自定義的類:new會調(diào)用構(gòu)造和析構(gòu)函數(shù),malloc不會調(diào)用構(gòu)造和析構(gòu)函數(shù);
- 分配失?。?/strong>new會拋出異常,malloc會返回空;
5、內(nèi)存泄漏
是指由于疏忽或錯誤造成程序未能釋放掉不再使用的內(nèi)存的情況,內(nèi)存泄漏并非指內(nèi)存在物理上的小時,而是應(yīng)用程序分配某段內(nèi)存后,由于設(shè)計(jì)錯誤,失去該段內(nèi)存的控制從而造成內(nèi)存浪費(fèi);
可能的原因:
- 1、申請后未釋放(最常見)
- 2、
void*
指針的釋放 - 3、
new[]
回收時沒有用delete[]
,數(shù)組的回收要注意
三、內(nèi)存拓展
1、內(nèi)存概念
計(jì)算機(jī)重要部件之一,是外存與CPU進(jìn)行溝通的橋梁。計(jì)算機(jī)所有程序都是在內(nèi)存運(yùn)行的,因此內(nèi)存的性能對計(jì)算機(jī)的影響非常大。內(nèi)存也稱為內(nèi)存儲器和主存儲器,作用是暫時存放CPU的運(yùn)算數(shù)據(jù),以及與硬盤等外部存儲器交換的數(shù)據(jù);
尋址空間:保存內(nèi)存地址的多少,通常我們說的4G內(nèi)存,就表示計(jì)算機(jī)能保存2的32次方個地址,也就是能找到這些地址上的二進(jìn)制信息;
尋址能力:每個地址里能存多少個bit
,現(xiàn)在的計(jì)算機(jī)大多數(shù)是16位機(jī)器了;
2、虛擬內(nèi)存
使得系統(tǒng)運(yùn)行實(shí)際的內(nèi)存空間比想象的大得多,虛擬內(nèi)存是可以遠(yuǎn)大于物理內(nèi)存的,同時主要為了使程序運(yùn)行的時候可以不限制于只訪問內(nèi)存大小,可以通過虛擬內(nèi)存地址去訪問磁盤空間;
每一個進(jìn)程虛擬內(nèi)存都是獨(dú)立的,獨(dú)立的享有計(jì)算機(jī)的內(nèi)存。虛擬內(nèi)存地址的大小是與地址總線位數(shù)相關(guān),物理內(nèi)存地址的大小是與物理內(nèi)存條的容量與磁盤容量相關(guān)。
四、思考
1、代碼中的b屬于棧區(qū)還是堆區(qū)?
void fun() { int *b = new int[14]; }
b是在棧區(qū)的變量,由于b是一個局部變量,隨著函數(shù)域 的結(jié)束被釋放,不需要程序員自行釋放,盡管b使用new進(jìn)行初始化,還是可以認(rèn)為分配在棧區(qū);
總結(jié):
本次系統(tǒng)的從內(nèi)存的基礎(chǔ)概念到內(nèi)存分配進(jìn)行了講解,內(nèi)存是我們開發(fā)中最重要的一部分,往往邏輯上的錯誤就會造成內(nèi)存泄漏,導(dǎo)致程序無法運(yùn)行。或者一些分配內(nèi)存的方式不夠細(xì)心,也會造成冗余內(nèi)存的使用。在目前的很多嵌入式板子上,針對內(nèi)存的接口是必備的,往往也都是基于malloc
修改;
還有一點(diǎn)需要注意,不管任何機(jī)器上運(yùn)行程序,操作的都是虛擬內(nèi)存,內(nèi)部通過頁表定位到對應(yīng)的物理內(nèi)存。關(guān)于硬件方面的本質(zhì),如果做嵌入式端的話需要深入研究。
到此這篇關(guān)于C++內(nèi)存分布及用法的文章就介紹到這了,更多相關(guān)C++內(nèi)存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++開發(fā)的Redis數(shù)據(jù)導(dǎo)入工具優(yōu)化
這篇文章主要介紹了C++開發(fā)的Redis數(shù)據(jù)導(dǎo)入工具優(yōu)化方法的相關(guān)資料,需要的朋友可以參考下2015-07-07C語言pow()函數(shù)實(shí)現(xiàn)求x的y次方的值
這篇文章主要介紹了C語言pow()函數(shù)實(shí)現(xiàn)求x的y次方的值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03C/C++實(shí)現(xiàn)動態(tài)數(shù)組的示例詳解
動態(tài)數(shù)組相比于靜態(tài)數(shù)組具有更大的靈活性,因?yàn)槠浯笮】梢栽谶\(yùn)行時根據(jù)程序的需要動態(tài)地進(jìn)行分配和調(diào)整,本文為大家介紹了C++實(shí)現(xiàn)動態(tài)數(shù)組的方法,需要的可以參考下2023-08-08