c++中,記憶體分為5個區:堆、棧、自由儲存區、全域性/靜態儲存區和常量儲存區。
棧:是由編譯器在需要時自動分配,不需要時自動清除的變數儲存區。通常存放區域性變數、函式引數等。
堆:是由new分配的記憶體塊,由程式設計師釋放(編譯器不管),一般乙個new與乙個delete對應,乙個new與乙個delete對應。如果程式設計師沒有釋放掉,資源將由作業系統在程式結束後自動**。
自由儲存區:是由malloc等分配的記憶體塊,和堆十分相似,用free來釋放。
全域性/靜態儲存區:全域性變數和靜態變數被分配到同一塊記憶體中(在c語言中,全域性變數又分為初始化的和未初始化的,c++中沒有這一區分)。
常量儲存區:這是一塊特殊儲存區,裡邊存放常量,不允許修改。
(注意:堆和自由儲存區其實不過是同一塊區域,new底層實現**中呼叫了malloc,new可以看成是malloc智慧型化的高階版本)
堆與棧的討論:
管理方式:
堆中資源由程式設計師控制(容易產生memory leak)。
棧資源由編譯器自動管理,無需手工控制。
系統響應:
對於堆,應知道系統有乙個記錄空閒記憶體位址的鍊錶,當系統收到程式申請時,遍歷該鍊錶,尋找第乙個空間大於申請空間的堆結點,刪除空閒結點鍊錶中的該結點,並將該結點空間分配給程式(大多數系統會在這塊記憶體空間首位址記錄本次分配的大小,這樣delete才能正確釋放本記憶體空間,另外系統會將多餘的部分重新放入空閒鍊錶中)。
對於棧,只要棧的剩餘空間大於所申請空間,系統為程式提供記憶體,否則報異常提示棧溢位。
空間大小:
堆是不連續的記憶體區域(因為系統是用鍊錶來儲存空閒記憶體位址,自然不是連續的),堆大小受限於計算機系統中有效的虛擬記憶體(32bit系統理論上是4g),所以堆的空間比較靈活,比較大。
棧是一塊連續的記憶體區域,大小是作業系統預定好的,windows下棧大小是2m(也有是1m,在編譯時確定,vc中可設定)。
碎片問題:
對於堆,頻繁的new/delete會造成大量碎片,使程式效率降低。
對於棧,它是乙個先進後出的佇列,進出一一對應,不會產生碎片。
生長方向:
堆向上,向高位址方向增長。
棧向下,向低位址方向增長。
分配方式:
堆都是動態分配(沒有靜態分配的堆)。
棧有靜態分配和動態分配,靜態分配由編譯器完成(如區域性變數分配),動態分配由alloca函式分配,但棧的動態分配的資源由編譯器進行釋放,無需程式設計師實現。
分配效率:
堆由c/c++函式庫提供,機制很複雜。所以堆的效率比棧低很多。
棧是極其系統提供的資料結構,計算機在底層對棧提供支援,分配專門暫存器存放棧位址,棧操作有專門指令。
C 中類的記憶體分布
如何計算類物件占用的位元組數?乙個空類的話1個位元組。這是為了保證n個連續空類宣告時,變數位址有偏移,防止變數覆蓋。非空類的話用關鍵字sizeof計算。如果手工計算就相當麻煩,光padding就一堆規則了。而且有些額外資訊比如虛函式 多個虛函式也只產生乙個vptr指標 等等。乙個類成員 當有虛函式時...
C 物件在記憶體中的分布
c 通過class的pointers和references來支援多型,這種程式風格就成為 物件導向 一 c 對多型的支援的三種方式 1.把乙個派生類指標隱式轉換成乙個基類指標 ex shape ps new circle 2.經由virtual function機制 ex ps rotate 2.經...
C語言在記憶體中的分布
2019獨角獸企業重金招聘python工程師標準 先認識記憶體中的幾個區,下面的區都在記憶體中,意味著掉電會丟失。但是這不意味著記憶體條裡面真的是這樣,包括作業系統的分頁都只是對記憶體的一種管理方式,或者說是虛擬的邏輯管理。堆區和棧區屬於動態區域,其他的屬於靜態區域,為什麼這麼說?來看看他們生成的過...