標籤:一段 nbsp 對象 固定 程式集 準備工作 處理 編譯器 情況
1、棧區(stack)
由編譯器自動分配釋放 ,存放函數的參數值,局部變數的值等。
2、堆區(heap)
一般由程式員分配釋放, 若程式員不釋放,程式結束時可能由OS回收 。
3、儲存的資料類型
堆(heap):儲存參考型別。比如:類、介面、數組等。
棧(stack):儲存實值型別,即儲存固定長度的資料。比如:整數、字元、結構、布爾、枚舉等。每個程式在執行時都有自己的堆棧,其他程式不能訪問該堆棧。
解釋一、
棧是編譯期間就分配好的記憶體空間,因此你的代碼中必須就棧的大小有明確的定義;
堆是程式運行期間動態分配的記憶體空間,你可以根據程式的運行情況確定要分配的堆記憶體的大小
解釋二、
存放在棧中時要管儲存順序,保持著先進後出的原則,他是一片連續的記憶體域,有系統自動分配和維護。
而堆是無序的,他是一片不連續的記憶體域,有使用者自己來控制和釋放,如果使用者自己不釋放的話,當記憶體達到一定的特定值時,通過記憶體回收行程(GC)來回收。
參考型別總是存放在堆中。
實值型別和指標總是放在它們被聲明的地方。
調用方法:系統先將一段編碼(堆的首部地址)放到棧上,緊接著放置方法的參數。然後代碼執行到方法時,尋找棧中放該堆首部地址的所有參數,並通過堆的首部地址來控制堆。
參考型別:總是放在堆當中。
當我們使用參考型別時,實際上只是在處理該類型的指標。而非參考型別本身,使用實值型別的話則是使用其本身。
三、棧 vs 堆:區別?
棧通常儲存著我們代碼執行的步驟
而堆上存放的則多是對象,資料等。
我們可以把棧想象成一個接著一個疊放在一起的盒子(越高記憶體位址越低)。當我們使用的時 候,每次從最頂部取走一個盒子,當一個方法(或類型)被調用完成的時候,就從棧頂取走(called a Frame,譯註:調用幀),接著下一個。
棧記憶體無需我們管理,也不受GC管理。當棧頂元素使用完畢,立馬釋放。而堆則需要GC(Garbage collection:垃圾收集器)清理。
堆則不然,像是一個倉庫,儲存著我們使用的各種對象等資訊,跟棧不同的是他們被調用完畢不會立即被清理掉。
堆和棧的區別可以用如下的比喻來看出:
使用棧就象我們去飯館裡吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等準備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。
使用堆就象是自己動手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大。
四、引用和實值型別如何分配?
我們先看一下兩個觀點:
觀點1,參考型別一般被分配在堆上。 一個實值型別變數,一般會分配在棧上
觀點2,實值型別和指標總是分配在被定義的地方,他們不一定被分配到棧上。 原因就是如果一個實值型別被聲明在一個方法體外並且在一個參考型別中,那它就會在堆上進行分配。
上文提及的棧(Stack),在程式啟動並執行時候,每個線程(Thread)都會維護一個自己的專屬線程堆棧。
當一個方法被調用的時候,主線程開始在所屬程式集的中繼資料中,尋找被呼叫者法,然後通過JIT即時編譯並把結果(一般是本地CPU指令)放在棧頂。CPU通過匯流排從棧頂取指令,驅動程式以執行下去。
此隨筆有整理其他大師的筆記,有不妥的及更好的解釋或者補充請留言,謝謝!
C#堆和棧的入門理解