基礎——堆和棧的區別

發表於2015-11-23

堆和棧的區別在許多的面試中都有提及,他們的區別在計算機程式設計中也是屬於非常基礎的部分,不過我之前一直沒去了解……

不過在瞭解之後也很簡單的。

首先我們要知道程式所佔的記憶體一共分為5大塊,分別是

1、堆

2、棧

3、初始化區

4、未初始化區

5、程式碼區


堆——由程式設計師分配記憶體釋放的,比如new指令、alloc指令和malloc指令

棧——由編譯器自己分配釋放的,用來存放一些引數值,區域性變數的值之類的,就是除了堆和static和const以外的就都是棧了,一般編譯器的棧大小是已經固定好的


借鑑一個程式程式碼的例子:

 

這是一個前輩寫的,非常詳細    
  //main.cpp    
  int   a   =   0;   全域性初始化區    
  char   *p1;   全域性未初始化區    
  main()    
  {    
  int   b;   棧    
  char   s[]   =   "abc";   棧    
  char   *p2;   棧    
  char   *p3   =   "123456";   123456/0在常量區,p3在棧上。    
  static   int   c   =0;   全域性(靜態)初始化區    
  p1   =   (char   *)malloc(10);    
  p2   =   (char   *)malloc(20);    
  分配得來得10和20位元組的區域就在堆區。    
  strcpy(p1,   "123456");   123456/0放在常量區,編譯器可能會將它與p3所指向的"123456"  
  優化成一個地方。    
  }    
a在初始化區

p1在未初始化區

b這裡雖然沒給他值,但是他還是佔有一個隨機值,位元組為4,放在了棧中

s陣列為字元陣列,已初始化,大小為4,放在棧中

p2指標,32位計中固定佔了4位元組,棧中

p3指標,4位元組,棧中,指向常量區中的123456/0的首位元組

c 初始化區

之後是為p1、p2開闢了10和20位元組的堆區域

strcpy是為p1賦值,如果進行了優化,就指向了常量區,否則就把值放入堆中


堆和棧的比較:

1、開闢方式

棧是在你定義之後直接由模擬器給你開闢的空間

例如p2,p3

堆是由程式設計師申請的大小,如malloc(10)就是申請10位元組大小的空間

直接用new的話就是申請物件所佔的位元組空間


2、大小

棧是固定的常量,由模擬器決定

堆的大小為計算機系統中有效的虛擬記憶體容量。所以堆的容量遠遠的大於棧


3、儲存方式

棧由於是編譯器申請的,所以它所開闢的空間都是連續行的,即使在釋放之後也不會產生什麼碎片。

堆得位置都是隨機生成的,所以他比較自由,例如連結串列你是沒法通過簡單的加上所佔位元組得到下一個鏈的位置,同時由於隨機,堆會產生碎片,不過用起來比較方便


4、響應

棧的響應速度快,不過棧所申請的記憶體必須小於剩餘空間,否則會報棧溢位

堆得響應速度偏慢,它在申請的時候會在一個空閒表找到一個堆節點大於所申請的空間,並且把這個節點分配給堆,多於的大小重新放入空閒表中

(PS:作業系統有一個記錄空閒記憶體地址的連結串列)(PPS: 所謂的碎片就是空閒表中太小的空間,在兩塊已經被申請的空間中間並且基本上不會被用到的)


5、效率

效率嘛,不用多想,肯定是棧快


總結

堆和棧各有好壞

棧快但又不靈活而且還小

堆慢但是靈活,可分配記憶體大

在使用上棧比堆簡單,所以若是佔記憶體小且不是特別的扣記憶體的話,不妨用棧的簡單


   

相關文章