亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

淺談C#中堆和棧的區別(附上圖解)

2020-01-24 02:24:39
字體:
來源:轉載
供稿:網友

線程堆棧:簡稱棧 Stack
托管堆: 簡稱堆 Heap

使用.Net框架開發程序的時候,我們無需關心內存分配問題,因為有GC這個大管家給我們料理一切。如果我們寫出如下兩段代碼:
代碼段1:

public int AddFive(int pValue){int result;result = pValue + 5;return result;}


代碼段2:

public class MyInt{ public int MyValue;}public MyInt AddFive(int pValue){MyInt result = new MyInt();result.MyValue = pValue + 5;return result;}

問題1:你知道代碼段1在執行的時候,pValue和result在內存中是如何存放,生命周期又如何?代碼段2呢?
要想釋疑以上問題,我們就應該對.Net下的棧(Stack)和托管堆(Heap)(簡稱堆)有個清楚認識,本立而道生。如果你想提高程序性能,理解棧和堆,必須的!
本文就從棧和堆,類型變量展開,對我們寫的程序進行庖丁解牛。
C#程序在CLR上運行的時候,內存從邏輯上劃分兩大塊:棧,堆。這倆基本元素組成我們C#程序的運行環境。

一,棧 vs 堆:區別?

棧通常保存著我們代碼執行的步驟,如在代碼段1中 AddFive()方法,int pValue變量,int result變量等等。而堆上存放的則多是對象,數據等。(譯者注:忽略編譯器優化)我們可以把棧想象成一個接著一個疊放在一起的盒子。當我們使用的時候,每次從最頂部取走一個盒子。棧也是如此,當一個方法(或類型)被調用完成的時候,就從棧頂取走(called a Frame,譯注:調用幀),接著下一個。堆則不然,像是一個倉庫,儲存著我們使用的各種對象等信息,跟棧不同的是他們被調用完畢不會立即被清理掉。

如圖1,棧與堆示意圖

(圖1)

棧內存無需我們管理,也不受GC管理。當棧頂元素使用完畢,立馬釋放。而堆則需要GC(Garbage collection:垃圾收集器)清理。


二,什么元素被分配到棧?什么被分配到堆?

當我們程序執行的時候,在棧和堆中分配有四種主要的類型:值類型,引用類型,指針,指令。

值類型:
在C#中,繼承自System.ValueType的類型被稱為值類型,主要有以下幾種(CLR2.0中支持類型有增加):
* bool
* byte
* char
* decimal
* double
* enum
* float
* int
* long
* sbyte
* short
* struct
* uint
* ulong
* ushort

引用類型:
以下是引用類型,繼承自System.Object:
* class
* interface
* delegate
* object
* string

指針:
在內存區中,指向一個類型的引用,通常被稱為“指針”,它是受CLR( Common Language Runtime:公共語言運行時)管理,我們不能顯示使用。需要注意的是,一個類型的引用即指針跟引用類型是兩個完全不同的概念。指針在內存中占一塊內存區,它本身只代表一個內存地址(或者null),它所指向的另一塊內存區才是我們真正的數據或者類型。如圖2:


(圖2)

指令:
后文對指令再做介紹。

三,如何分配?
我們先看一下兩個觀點:
觀點1,引用類型總是被分配在堆上。(正確?)
觀點2,值類型和指針總是分配在被定義的地方,他們不一定被分配到棧上。(這個理解起來有點難度,需要慢慢來)

上文提及的棧(Stack),在程序運行的時候,每個線程(Thread)都會維護一個自己的專屬線程堆棧。
當一個方法被調用的時候,主線程開始在所屬程序集的元數據中,查找被調用方法,然后通過JIT即時編譯并把結果(一般是本地CPU指令)放在棧頂。CPU通過總線從棧頂取指令,驅動程序以執行下去。

下面我們以實例來詳談。

還是我們開篇所列的代碼段1:

public int AddFive(int pValue){int result;result = pValue + 5;return result;}

當AddFive方法開始執行的時候,方法參數(parameters)則在棧上分配。如圖3:

(圖3)

注意:方法并不在棧中存活,圖示僅供參考。
接著,指令指向AddFive方法內部,如果該方法是第一次執行,首先要進行JIT即時編譯。如圖4:


(圖4)

當方法內部開始執行的時候,變量result被分配在棧上,如圖5:


(圖5)

方法執行完畢,而且方法返回后,如圖6所示:

(圖6)

在方法執行完畢返回后,棧上的區域被清理。如圖7:

(圖7)

以上看出,一個值類型變量,一般會分配在棧上。那觀點2中所述又做何理解?“值類型和指針總是分配在被定義的地方,他們不一定被分配到棧上”。
原因就是如果一個值類型被聲明在一個方法體外并且在一個引用類型中,那它就會在堆上進行分配。
還是代碼段2:

public class MyInt{ public int MyValue;}public MyInt AddFive(int pValue){MyInt result = new MyInt();result.MyValue = pValue + 5;return result;}

當線程開始執行AddFive方法的時候,參數被分配到棧上,如圖8所示:

(圖8)
由于MyInt是一個引用類型,所以它被分配到堆上,并且在棧中生成一個指針(result),如圖9:

(圖9)
AddFive方法執行完畢時的情況如圖10:

(圖10)

棧上內存被清理,堆中依然存在,如圖11:


(圖11)

當程序需要更多的堆空間時,GC需要進行垃圾清理工作,暫停所有線程,找出所有不可達到對象,即無被引用的對象,進行清理。并通知棧中的指針重新指向地址排序后的對象。現在我們應該知道,了解棧和堆,對我們開發出高性能程序的重要性。當我們使用引用類型的時候,一般是對指針進行的操作而非引用類型對象本身。但是值類型則操作其本身。
接下來,我們用例子說明這一點。

例1:

public int ReturnValue(){int x = new int();x = 3;int y = new int();y = x; y = 4; return x;}

執行結果為3,稍作修改:

例2:

public class MyInt{public int MyValue;}public int ReturnValue2(){MyInt x = new MyInt();x.MyValue = 3;MyInt y = new MyInt();y = x; y.MyValue = 4; return x.MyValue;}

執行結果為4。

我們來分析下原因,其實例1的跟以下代碼所起效用一樣:

public int ReturnValue(){int x = 3;int y = x; y = 4;return x;}


如圖12所示,在棧上x和y分別占用一塊內存區,互不干擾。

(圖12)

而例2,與以下代碼所起效用一樣:

public int ReturnValue2(){MyInt x;x.MyValue = 3;MyInt y;y = x; y.MyValue = 4;return x.MyValue;}

如圖13所示,


(圖13)
棧上的指針x和y指向堆上同一個區域,修改其一必會改變堆上的數據。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产亚洲一区二区在线| 欧美日韩亚洲一区二区| 国产91在线播放九色快色| 91精品国产91久久久久久久久| 欧美日韩国产va另类| 美女999久久久精品视频| 欧美专区日韩视频| 日韩中文字幕欧美| 国产婷婷成人久久av免费高清| 成人在线视频网站| 久久久久国产视频| 中文字幕日韩欧美精品在线观看| 成人黄色av播放免费| 欧美精品久久一区二区| 久久好看免费视频| 国产日韩欧美成人| 国产中文字幕91| 亚洲自拍偷拍福利| 91精品国产色综合久久不卡98口| 国产一级揄自揄精品视频| 亚洲精品成人av| 久久免费少妇高潮久久精品99| 亚洲精品国产精品国产自| 亚洲一区二区福利| 久久久精品国产一区二区| 亚洲成人激情小说| 日韩精品视频免费在线观看| 国产精品久久久久久久久久ktv| 欧洲亚洲免费视频| 国产精品网红直播| 伊人久久大香线蕉av一区二区| 亚洲va久久久噜噜噜久久天堂| 日韩美女免费视频| 欧美人在线观看| 国产91在线播放精品91| 日韩精品高清视频| 久久久欧美精品| 国产精品第100页| 亚洲韩国欧洲国产日产av| 国产日产欧美a一级在线| 91精品国产99| 欧美日韩在线视频首页| 亚洲国模精品一区| 欧美性xxxxxxx| 亚洲一区二区久久| 2021久久精品国产99国产精品| 亚洲毛片在线观看.| 国产欧美精品日韩| 国产精品吊钟奶在线| 中文字幕精品网| 91精品国产自产91精品| 日本一区二区三区在线播放| 国产亚洲精品一区二555| 日韩中文字幕免费看| 国产精品一区二区三区成人| 欧美丝袜一区二区| 91精品国产91久久久久久最新| 欧美怡春院一区二区三区| 日韩中文字幕在线视频播放| 亚洲欧美中文日韩在线v日本| 国产成人精品免高潮费视频| 欧美成人性色生活仑片| 美女黄色丝袜一区| 欧美激情视频免费观看| 高清欧美电影在线| 精品无人区太爽高潮在线播放| 亚洲丁香婷深爱综合| 日韩在线观看视频免费| 国产精品大片wwwwww| 91久久国产综合久久91精品网站| 中文字幕日韩在线观看| 久久天堂电影网| 国产女精品视频网站免费| 久操成人在线视频| 欧美肥臀大乳一区二区免费视频| 色一区av在线| 欧美尺度大的性做爰视频| 欧日韩不卡在线视频| 激情av一区二区| 麻豆乱码国产一区二区三区| 午夜精品福利在线观看| 欧美在线视频在线播放完整版免费观看| 欧美大片免费观看在线观看网站推荐| 色老头一区二区三区在线观看| 精品日韩美女的视频高清| 91免费看国产| 国产精品爽爽爽| 久久精品人人做人人爽| 91精品在线观| 亚洲开心激情网| 精品日本美女福利在线观看| 日韩av在线播放资源| 亚洲精品久久7777777| 欧美色视频日本高清在线观看| 国产亚洲欧美日韩精品| 黑人巨大精品欧美一区二区| 亚洲xxxxx电影| 久久精品人人爽| 成人免费网站在线看| 亚洲夜晚福利在线观看| 国产99久久精品一区二区| 中文字幕亚洲欧美一区二区三区| 欧美另类第一页| 国产大片精品免费永久看nba| 中文字幕免费精品一区高清| 成人免费视频a| 亚洲综合精品伊人久久| 国产福利视频一区二区| 欧美国产日韩免费| 欧美色视频日本版| 亚洲变态欧美另类捆绑| 亚洲美女福利视频网站| 日本精品久久久久影院| 欧美一区二区三区图| 国产精品久久久久久av福利软件| 国产精品美腿一区在线看| 国产一区红桃视频| 国产精品欧美日韩| 91精品国产高清自在线看超| 久久久久久久久久久人体| 亚洲资源在线看| 欧美精品在线免费观看| 成人亲热视频网站| 68精品国产免费久久久久久婷婷| 久久久噜噜噜久噜久久| 亚洲国产欧美在线成人app| 中文字幕亚洲欧美日韩在线不卡| 国产亚洲一区二区精品| 欧美性猛交xxxx乱大交蜜桃| 国产精品黄页免费高清在线观看| 777午夜精品福利在线观看| 91成人在线视频| 亚洲国产黄色片| 日韩专区中文字幕| 亚洲国产女人aaa毛片在线| 成人97在线观看视频| 精品久久久中文| 一色桃子一区二区| 社区色欧美激情 | 国产91对白在线播放| 亚洲香蕉成视频在线观看| 成人免费自拍视频| 亚洲成人黄色在线| 亚洲欧美日韩精品久久| 亚洲iv一区二区三区| 日韩欧美在线看| 国产亚洲欧美另类中文| 91性高湖久久久久久久久_久久99| 久久久久久免费精品| 久久国产精品99国产精| 亚洲a区在线视频| 亚洲一区免费网站| 欧美精品一区在线播放| 亚洲精品自在久久| 国外色69视频在线观看| 奇米4444一区二区三区| 亚洲18私人小影院| 亚洲激情电影中文字幕| 91亚洲精品在线| 亚洲性视频网站| 日韩在线资源网| 91亚洲精品视频| 日本精品久久久久久久| 亚洲色图美腿丝袜|