.net框架中值类型和引用类型的内存分配

时间:2009-07-15 09:53:16

标签: .net memory-management

是否有一篇我可以阅读的高级文章可以解释如何在.net框架中为不同类型(值和引用)分配内存。

例如,我们知道值类型在堆栈上分配了空间,但是如何管理?

如何在堆中管理引用类型以及存储实际值的位置。 (类似于任何类的引用类型将包含许多值类型,它们保存在何处以及如何管理)

5 个答案:

答案 0 :(得分:10)

这比你想象的要复杂得多。甚至你声称“值类型在堆栈上分配”也是不正确的。例如:

class Foo
{
    int x;
}

int是一个值类型,但x的值总是在堆上,因为它将与Foo实例的其余数据一起存储,这是一个类。

此外,匿名函数和迭代器块的捕获变量使生活变得更加棘手。

我有一个article about C# heap/stack memory您可能会觉得有用,但您可能还想阅读Eric Lippert在"The stack is an implementation detail"上的博客文章。特别是,未来的C#编译器可以决定将所有局部变量存储在堆上,使用堆栈只是为了保存对在方法开始时创建的实例的引用...这不会违反C#规范所有

答案 1 :(得分:3)

值类型在已定义的位置“已分配”。

这意味着什么取决于你定义它的位置:

  • 在类/结构中,作为该结构中的字段,在内存中放大类/结构以适合其中的值类型值
  • 作为方法中的局部变量,在堆栈上,或作为寄存器,或作为生成的类中的字段(当使用“闭包”时),取决于优化
  • 作为方法的参数,在堆栈上或作为寄存器,取决于优化

引用类型是双重值。引用类型的核心是指针,指针值遵循与“分配”相同的规则作为值类型,但是一旦在其中存储了值,即。对象的引用,该对象在其他地方的堆上。

换句话说,引用变量本身被“分配”为值类型,但它引用的对象在堆上。

当您从类构造对象时,会在堆上分配空间以适合该类的所有字段+该空间中的一些开销。

我似乎记得Jon Skeet有一篇关于这个主题的文章,我相信他很快就能得到答案,所以请继续关注。

答案 2 :(得分:2)

这篇文章看起来很先进而不会过分。它应该为您提供更好的理解:

http://www.simple-talk.com/dotnet/.net-framework/understanding-garbage-collection-in-.net/

答案 3 :(得分:2)

记住规则,引用类型总是转到堆,而值类型总是转到它们声明的位置。如果在方法之外声明了Value Type,但在Reference Type中,它将被放置在堆上的Reference Type中。

答案 4 :(得分:1)

当调用方法时,值类型所需的空间量是预先知道的(它可以由编译器计算)。此空间在堆栈上分配,仅在方法调用期间可用。对于每个新方法调用,堆栈上使用的内存都会增长,当方法退出时,它会收缩回到之前的级别。

引用类型在堆上分配。堆基本上是用于此目的的内存块。存储在堆上的对象主要是存储在分配给对象的内存中的对象的字段。因此,值类型字段存储在堆上的对象“内部”。引用类型字段存储为引用对象的引用(或指针)。堆上的内存由垃圾回收管理。这是一个复杂的主题,但短篇小说是分配给堆上未使用的对象的内存被释放,因此可以由垃圾收集器定期重用。