C 學習筆記 6 C 記憶體管理

2021-10-07 14:20:48 字數 2032 閱讀 6511

3 堆和棧的區別

4 記憶體的申請和釋放

5 malloc/free與new/delete

參考資料

內存在程式編譯的時候就已經分配好了,這塊內存在程式的整個執行期間都存在。

例如全域性變數,static靜態成員變數

執行函式時,函式內部變數的儲存單元可以在棧上建立,函式執行結束時這些儲存單元自動釋放。棧記憶體分配運算置於處理器的指令集中,效率很高,但是分配的記憶體容量有限。

也稱為動態記憶體分配。程式在執行的時候用malloc或new申請任意多少記憶體,程式設計師自己負責在何時用free或delete來釋放這塊記憶體。動態記憶體的生命週期由程式設計師決定,使用非常靈活,但如果在堆上分配了空間,就有責任**它,否則執行的程式會出現洩漏,頻繁地分配和釋放不同大小的堆空間將會產生堆內碎塊。也就是我們常說的記憶體碎片。

(1) 管理方式:棧由編譯器自動管理,無需手工控制;堆釋放工作由程式設計師控制,容易產生memory leak。

(2) 空間大小:一般來講在32位系統下,堆記憶體可以達到4g的空間。但棧一般都是有一定的空間大小的。

(3) 碎片問題:對於堆來講,頻繁的new/delete勢必會造成記憶體空間的不連續,從而造成大量的碎片,使程式效率降低。棧則不會存在這個問題。

(5) 分配方式:堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,比如區域性變數的分配。動態分配由alloca函式進行分配,但是棧的動態分配和堆是不同的,它的動態分配是由編譯器進行釋放,無需手工實現。

(6) 分配效率:棧是機器系統提供的資料結構,計算機會在底層對棧提供支援:分配專門的暫存器存放棧的位址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是c/c++函式庫提供的,它的機制是很複雜的,例如為了分配一塊記憶體,庫函式會按照一定的演算法(具體的演算法可以參考資料結構/作業系統)在堆記憶體中搜尋可用的足夠大小的空間,如果沒有足夠大小的空間(可能是由於記憶體碎片太多),就有可能呼叫系統功能去增加程式資料段的記憶體空間,這樣就有機會分到足夠大小的記憶體,然後進行返回。顯然,堆的效率比棧要低得多。

申請記憶體:int *p = new int;

釋放記憶體:delete p;

申請塊記憶體:int *arr=new int[10];

釋放塊記憶體:delete arr;

記憶體申請是否一定成功?釋放記憶體需要注意什麼?

(1) malloc/free是c程式中的庫函式,需要標頭檔案支援;new/delete是c++中的操作符,可以被過載。刪除陣列delete p,指標釋放後,要將指標置空。

(2) malloc和new都是在堆上分配記憶體。

(3) malloc分配記憶體失敗時返回null;new記憶體分配失敗時,會丟擲bac_alloc異常。

(4) malloc/free是面向記憶體的,不可以呼叫建構函式和析構函式;new/delete是物件導向的,可以呼叫建構函式和析構函式,new可認為是malloc+建構函式。

(5) malloc不能初始化物件;new可以,如int *p = new int(2)。

(6) malloc返回的指標是void 型別,需要通過強制型別轉換將void指標轉換成我們需要的型別;而new返回的指標是它分配空間的型別。

[1]

[2] c++記憶體管理

[3] 經典面試題之new和malloc的區別

C 學習筆記6 C 中的引用

c 中三目運算子可以返回變數本身,那麼c 對三目運算子進行了怎樣的處理?關於變數名 變數時一段實際連續儲存空間的別名,程式中通過變數名來申請並命名儲存空間,通過變數的名字可以使用儲存空間。我們考慮一下 對於這一段記憶體,是否只能有乙個別名?在c 中新增加了引用的概念 引用可以看做是乙個已經定義變數的...

c 學習6 C 中的反射

反射的定義 審查元資料並收集關於它的型別資訊的能力。元資料 編譯以後的最基本資料單元 就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙個字段定義表,和乙個方法定義表等。system.reflection命名空間包含的幾個類,允許你反射 解析 這些元資料表的 system.refl...

C學習筆記 記憶體管理

乙個c語言變數的作用域可以是 塊 作用域,函式作用域或者檔案作用域 塊是 之間的一段 同乙個 塊不可以有重名變數 auto自動變數 一般情況下 塊內部定義的變數都是自動變數 也可以顯示的使用aotu關鍵字 auto int i register暫存器變數 通常變數在記憶體當中,如果能把變數放到cpu...