標籤:
首先堆棧和堆(託管堆)都在進程的虛擬記憶體中。(在32位處理器上每個進程的虛擬記憶體為4GB)
堆棧stack :
堆棧中儲存實值型別。
堆棧實際上是向下填充,即由高記憶體位址指向地記憶體位址填充。
堆棧的工作方式是先分配記憶體的變數後釋放(先進後出原則)。
堆棧中的變數是從下向上釋放,這樣就保證了堆棧中先進後出的規則不與變數的生命週期起衝突!
堆棧的效能非常高,但是對於所有的變數來說還不太靈活,而且變數的生命週期必須嵌套。
通常我們希望使用一種方法分配記憶體來儲存資料,並且方法退出後很長一段時間內資料仍然可以使用。
此時就要用到堆(託管堆):
堆(託管堆)儲存參考型別。
堆(託管堆)在.NET中的堆由垃圾收集器自動管理。 與堆棧不同,堆是從下往上分配,所以自由的空間都在已用空間的上面。
比如建立一個對象:
Customer cus= new Customer();
申明一個Customer的引用cus,在堆棧上給這個引用分配儲存空間。這僅僅只是一個引用,
不是實際的Customer對象!cus佔4個位元組的空間, 包含了儲存Customer的引用地址。接著分配堆上的記憶體以
儲存Customer對象的執行個體,假定Customer 對象的執行個體是32位元組,為了在堆上找到一個儲存Customer對象的
儲存位置。.NET運行庫在堆中搜尋第一個從未使用的,32位元組的連續Block StorageCustomer對象的執行個體!然後把分配
給Customer對象執行個體的地址賦給cus變數!
從這個例子中可以看出,建立對象引用的過程比建立值變數的過程複雜,且不能避免效能的降低!
實際上就是.NET運行庫儲存對的狀態資訊,在堆中添加新資料時,堆棧中的引用變數也要更新。效能上損失很多!
有種機制在分配變數記憶體的時候,不會受到堆棧的限制:把一個引用變數的值賦給一個相同類型的變數,
那麼這兩個變數就引用同一個堆中的對象。當一個應用變數出範圍時,它會從堆棧中刪除。
但引用對象的資料仍然保留在堆中,一直到程式結 或者該資料不被任何變數應用時,垃圾收集器會刪除它。
C#中的堆棧與堆(託管堆) [轉自互連網]