2009-07-15 64 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

请记住规则,引用类型总是去堆,而值类型总是在他们被声明的地方。如果值类型在方法之外声明,但在引用类型内部,它将被放置在堆中的引用类型中。