首先堆棧和堆(托管堆)都在進(jìn)程的虛擬內存中。(在32位處理器上每個(gè)進(jìn)程的虛擬內存為4GB)
堆棧stack
堆棧中存儲值類(lèi)型。
堆棧實(shí)際上是向下填充,即由高內存地址指向地內存地址填充。
堆棧的工作方式是先分配內存的變量后釋放(先進(jìn)后出原則)。
堆棧中的變量是從下向上釋放,這樣就保證了堆棧中先進(jìn)后出的規則不與變量的生命周期起沖突!
堆棧的性能非常高,但是對于所有的變量來(lái)說(shuō)還不太靈活,而且變量的生命周期必須嵌套。
通常我們希望使用一種方法分配內存來(lái)存儲數據,并且方法退出后很長(cháng)一段時(shí)間內數據仍然可以使用。此時(shí)就要用到堆(托管堆)!
堆(托管堆)heap
堆(托管堆)存儲引用類(lèi)型。
此堆非彼堆,.NET中的堆由垃圾收集器自動(dòng)管理。
與堆棧不同,堆是從下往上分配,所以自由的空間都在已用空間的上面。
比如創(chuàng )建一個(gè)對象:
Customer cus;
cus = new Customer();
申明一個(gè)Customer的引用cus,在堆棧上給這個(gè)引用分配存儲空間。這僅僅只是一個(gè)引用,不是實(shí)際的Customer對象!
cus占4個(gè)字節的空間,包含了存儲Customer的引用地址。
接著(zhù)分配堆上的內存以存儲Customer對象的實(shí)例,假定Customer對象的實(shí)例是32字節,為了在堆上找到一個(gè)存儲Customer對象的存儲位置。
.NET運行庫在堆中搜索第一個(gè)從未使用的,32字節的連續塊存儲Customer對象的實(shí)例!
然后把分配給Customer對象實(shí)例的地址賦給cus變量!
從這個(gè)例子中可以看出,建立對象引用的過(guò)程比建立值變量的過(guò)程復雜,且不能避免性能的降低!
實(shí)際上就是.NET運行庫保存對的狀態(tài)信息,在堆中添加新數據時(shí),堆棧中的引用變量也要更新。性能上損失很多!
有種機制在分配變量?jì)却娴臅r(shí)候,不會(huì )受到堆棧的限制:把一個(gè)引用變量的值賦給一個(gè)相同類(lèi)型的變量,那么這兩個(gè)變量就引用同一個(gè)堆中的對象。
當一個(gè)應用變量出作用域時(shí),它會(huì )從堆棧中刪除。但引用對象的數據仍然保留在堆中,一直到程序結束 或者 該數據不被任何變量應用時(shí),垃圾收集器會(huì )刪除它。
聯(lián)系客服