對C# 中堆棧,堆,值類型,引用類型的理解

1,什麼是GC
GC的全稱是garbage collection,中文名稱垃圾回收,是.net中對內存管理的一種功能。垃圾回收器跟蹤並回收託管內存中分配的對象,定
期執行垃圾回收以回收分配給沒有有效引用的對象的內存。當使用可用內存不能滿足內存請求時,GC會自動進行。在進行垃圾回收時,垃圾回收器回首先搜索內存中的託管對象,然後從託管代碼中搜索被引用的對象並標記爲有效,接着釋放沒有被標記爲有效的對象並收回內存,最後整理內存將有效對象挪動到一起。這就是GC的四個步驟。
由上可見,GC是很影響性能的,所以一般說來這種事情況還是儘量少發生爲好。
爲了減少一些性能影響,.net的GC支持對象老化,或者說分代的概念,代是對象在內存中相對存現時期的度量單位,對象的代數或存現時期
說明對象所屬的代。目前.net的垃圾回收器支持三代。每進行一次GC,沒有被回收的對象就自動提升一代。較近創建的對象屬於較新的代,比在應用程序生命週期中較早創建的對象的代數低。最近代中的對象位於零代中。每一次GC的時候,都首先回收零代中的對象,只有在較低代數的對象回收完成後仍不能滿足需求的情況下才回收較高代數的對象。

2,讀文章,看到了一個關於堆和棧(堆棧)的區別的比喻。很形象:
使用棧就象我們去飯館裏吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等準備工作和洗碗、刷鍋
等掃尾工作,他的好處是快捷,但是自由度小。
使用堆就象是自己動手做喜歡吃的菜餚,比較麻煩,但是比較符合自己的口味,而且自由度大。

3,GC和堆棧、堆
由前述堆棧和堆的概念可以看出,堆棧不存在垃圾收集的問題,只需要直接壓棧即可,而堆,則面臨着很複雜的垃圾回收的問題。GC完全是
對堆進行操作的,而對堆中對象是否有效的判斷則是通過遍歷堆棧來實現的。這裏涉及到一個引用計數的概念,引用計數是對堆中對象被引用次數的統計,當一個對象的引用計數爲零了,那麼這個對象就可以被回收了。在進行GC的時候,垃圾回收器遍歷堆棧,當發現一個堆地址的時候,它就將堆中該地址上的對象的引用計數加1,然後銷燬堆中所有引用計數爲零的對象,回收內存並整理堆中的碎片。

4,類實例化的步驟
類是最常見也是我們用的最多的一種引用類型,我們知道實例化一個類使用的是一個我們司空見慣的語句:
ClassA ca = new ClassA();
那麼這短短的一句話中,計算機又做了些什麼事情呢?
實際上,計算機在這個過程中大致做了這麼幾件事:
首先,在ClassA ca的時候,生成一個空的引用指針,並將它推入堆棧中:
然後,在new ClassA()的時候,生成ClassA的新的實例,並放入堆中:
在賦值號=這一步,將ca的引用指針指向剛剛生成的新實例:
這個時候,纔算完成了整條語句的操作。

5,特例:string 類型與堆
大家知道,string類型是一種引用類型。但它又有一些值類型的特徵。比如指向同一個字符串的兩個string變量,如果其中一個變量值發生
了改變,卻不會影響到另外一個string變量。這就是因爲:
(1)CLR使用了一種叫字符串駐留的技術,對於
string   str1="abc";
string   str2="abc";
當CLR初始化時,會創建一個內部的散列表,其中的鍵爲字符串,值爲指向託管堆中字符串的引用。剛開始,散列表爲空,JIT編譯器編譯方法
時,會在散列表中查找每一個文本常量字符串,首先會查找"abc"字符串,並且因爲沒有找到,編譯器會在託管堆中構造一個新的指向"abc"的String對象引用,然後將"abc"字符串和指向該對象的引用添加到散列表中。
  接着,在散列表中查找第二個"abc",這一次由於找到了該字符串,所以編譯器不會執行任何操作,代碼中再沒有其它的文本常量字符串
,編譯器的任務完成,代碼開始執行。執行時,CLR發現第一個語句需要一個"abc"字符串引用,於是,CLR會在內部的散列表中查找"abc",並且會找到,這樣指向先前創建的String對象的引用就被保存在變量s1中,執行第二條語句時,CLR會再一次在散列表中查找"abc",並且仍然會找到,指向同一個String對象的引用會被保存在變量s2中,到此s1和s2指向了同一個引用,所以System.Object.Equals(s1,s2)就會返回true了。
(2)當使用重載操作符”=”給string對象賦值時,string的對象是引用類型,它保留在堆上,而不是堆棧上.因此,當把一個字符串賦給另一個字
符串時,會得到對內存中同一個字符串的兩個引用.例如,修改其中一個字符串,就會創建一個全新的string對象(注意,這個過程發生在”=”中),而另一個字符串沒有改變.

6,C#中值類型分配在堆棧中。
值類型:bool,byte,char,decimal,double,enum,float,int,long,sbyte,short,struct,uint,ulong,ushort.
7,C#中引用類型分配在堆中,在堆棧中創建一個指向到堆的引用,返回給聲明的變量。
引用類型:class,delegate,interface,object,string

發佈了26 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章