2009-07-15 54 views
4

是否有一篇高級文章,我可以閱讀它,可以解釋如何在.net框架中爲不同類型(值和引用)分配內存。.net框架中值類型和引用類型的內存分配

例如我們知道值類型是在堆棧上分配空間,但是如何管理?

另外如何在堆中管理引用類型以及存儲實際值的位置。 (像任何類的引用類型將包含許多值類型,它們在哪裏被保存以及它們如何被管理)

回答

1

當調用方法時,預先知道值類型所需的空間量(它可以通過編譯器)。該空間分配在堆棧上,僅在方法調用期間可用。對於每個新方法的調用,堆棧中使用的內存都會增長,當方法退出時,它會縮回到先前的級別。

引用類型分配在堆上。堆基本上是用於此目的的一塊內存。存儲在堆上的對象主要是存儲在分配給對象的內存中的對象的字段。因此,值類型字段被存儲在堆內的對象「內部」。引用類型字段存儲爲引用對象的引用(或指針)。堆上的內存由垃圾回收管理。這是一個複雜的主題,但簡短的故事是分配給堆中未使用對象的內存被釋放,因此可以被垃圾收集器定期重用。

10

它比你想象的更復雜。即使你聲稱「價值類型分配在堆棧上」也是不正確的。例如:

class Foo 
{ 
    int x; 
} 

int是值類型,但是x的值將總是在堆上,因爲它將被存儲在與數據的其餘部分爲富的實例,它是一類。

此外,匿名函數和迭代器塊的捕獲變量使生活更加棘手。

我有一個article about C# heap/stack memory你可能會覺得有用,但你也可能想閱讀Eric Lippert的博文"The stack is an implementation detail"。特別是,未來的C#編譯器可以決定將所有局部變量存儲在堆中,使用堆棧來保存對在方法開始時創建的實例的引用......這不會違反C#規範所有。

3

值類型是「分配」的,在其中定義。

這意味着什麼取決於你在哪裏把它定義:

  • 在一個類/結構,如在結構領域,擴大在內存中的類/結構在那裏
  • 以適應值類型值
  • 作爲方法中,堆棧中,寄存器或生成類中的局部變量(使用「閉包」時),取決於優化
  • 作爲方法的參數,在堆棧上或作爲寄存器,取決於優化

引用類型是一種雙值。引用類型的核心是一個指針,指針值遵循與「值」類型相同的「分配」規則,但是一旦存儲了值,即。對某個對象的引用,該對象位於其他地方的堆上。

換句話說,引用變量本身是「分配」的值類型,但它引用的對象位於堆上。

當你從一個類構造一個對象時,空間被分配到堆上以適應該類的所有字段+該空間中的一些開銷。

我似乎想起Jon Skeet寫了一篇關於這個主題的文章,我確信他很快就會回答一個答案,敬請期待。

+3

他在那裏,而我正在輸入我的答案。 – 2009-07-15 10:14:32

2

請記住規則,引用類型總是去堆,而值類型總是在他們被聲明的地方。如果值類型在方法之外聲明,但在引用類型內部,它將被放置在堆中的引用類型中。