什麼時候用堆,什麼時候用棧?

2021-06-28 05:52:53 字數 2313 閱讀 6801

參考文章:

《c++面試題之記憶體分配》

一、首先,回顧一下c、c++的記憶體分配機制。

乙個c、c++程式編譯時記憶體分為5大儲存區:

堆區、棧區、靜態區(全域性區)、文字常量區(儲存字串常量)、程式**區(存放二進位制程式)

下面主要闡述前面三個。

(1)靜態儲存區域:

靜態儲存區域的

內存在程式編譯時就已經分配好,這塊內存在程式的整個執行期間都存在。速度快、不容易出錯,因為有系統會善後。例如全域性變數,static變數等。

(2)棧:

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

(3)堆:

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

二、下面來比較一下堆和棧的區別。

堆和棧的主要區別由以下幾點:

1、管理方式不同;

2、空間大小不同;

3、能否產生碎片不同;

4、生長方向不同;

5、分配方式不同;

6、分配效率不同;

(1)管理方式

對於棧來講,是由編譯器自動管理,無需我們手工控制;對於堆來說,釋放工作由程式設計師控制,容易產生記憶體洩露。

(2)空間大小:

一般來講在32位系統下,堆記憶體可以達到4g的空間,從這個角度來看 堆記憶體幾乎是沒有什麼限制的。但是對於棧來講,一般都是有一定的空間大小的,例如,在vc6下面,預設的棧空間大小是1m。當然,這個值可以修改。

(3)碎片問題

對於堆來講,頻繁的new/delete勢必會造成記憶體空間的不連續,從而造成大量的碎片,使程式效率降低。對於棧來講,則不會存在這個問題,因為棧是先進後出的佇列,他們是如此的一一對應,以至於永遠都不可能有乙個記憶體塊從棧中間彈出,在他彈出之前,在他上面的後進的棧內容已經被彈出,詳細的可以參考資料結構。

(4)生長方向

對於堆來講,生長方向是向上的,也就是向著記憶體位址增加的方向;對於棧來講,它的生長方向是向下的,是向著記憶體位址減小的方向增長。

(5)分配方式

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

(6)分配效率

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

本文總結:

從上面的討論我們可以看出:

(1)與堆相比,棧不會導致記憶體碎片,分配效率高。

所以棧在程式中是應用最廣泛的,就算是函式的呼叫也利用棧去完成,函式呼叫過程中的引數,返回位址, ebp和區域性變數都採用棧的方式存放。如果少量資料需要頻繁的操作,那麼在程式中動態申請少量棧記憶體(例如使用alloca函式),會獲得很好的效能提公升。

(2)堆可以申請的記憶體大很多。

與堆相比,棧的使用不是那麼靈活,如果分配大量的記憶體空間,推薦使用堆記憶體。

很多人說,如果變數要使用的記憶體長度不確定的時候,就是使用malloc或者new等申請動態記憶體。

但是這是不正確的,從上面的討論可以看出,在棧上也可以為長度不確定的變數動態申請記憶體。

不過在棧上動態申請記憶體需要注意一些問題。

《alloca——可以在棧中動態分配記憶體的函式》

什麼時候用exists 什麼時候用in

in not in exists not exists 使用exists,oracle會首先檢查主查詢,然後執行子查詢直到它找到第乙個匹配項,這就節省了時間。oracle在執行in子查詢時,首先執行 子查詢,並將獲得的結果列表存放在乙個加了索引的臨時表中。在執行子查詢之前,系統先將主查詢掛起 待子查...

什麼時候用GET?什麼時候用POST?

get和post兩種方法都是將資料送到伺服器,但你該用哪一種呢?http標準包含這兩種方法是為了達到不同的目的。post用於建立資源,資源的內容會被編入http請示的內容中。例如,處理訂貨表單 在資料庫中加入新資料行等。當請求無 時 如進行搜尋 便可使用get方法 當請求有 時 如新增資料行 則用p...

什麼時候用DFS,什麼時候用BFS

什麼時候用 dfs,什麼時候用 bfs?二維陣列的題目,n小於 20的,適用 dfs。而一般 n 200 n 1000 這種,一定不可能用 dfs去做。而且並不只是整個題目不能用 dfs,其中的 每一步也不能使用 dfs。bfs的基本步驟 1.將初始點 乙個或多個 加入乙個集合尾 2.從集合頭取出點...