.net 框架中值类型和引用类型的内存分配
Posted
技术标签:
【中文标题】.net 框架中值类型和引用类型的内存分配【英文标题】:memory allocation of value types and reference types in .net framework 【发布时间】:2010-11-10 22:56:35 【问题描述】:是否有一篇我可以阅读的高级文章可以解释如何在 .net 框架中为不同类型(值和引用)分配内存。
例如,我们知道值类型是在堆栈上分配的空间,但它是如何管理的?
还有如何在堆中管理引用类型以及实际值存储在哪里。 (引用类型和任何Class一样都会包含很多值类型,它们保存在哪里以及如何管理)
【问题讨论】:
【参考方案1】:记住规则,引用类型总是去堆,而值类型总是去它们被声明的地方。如果值类型在方法之外声明,但在引用类型内,它将被放置在堆上的引用类型中。
【讨论】:
【参考方案2】:值类型在定义的地方“分配”。
这意味着什么取决于你在哪里定义它:
在类/结构中,作为该结构中的字段,扩大内存中的类/结构以适应其中的值类型值 作为方法中的局部变量、堆栈中、寄存器或生成类中的字段(使用“闭包”时),具体取决于优化 作为方法的参数,在堆栈上或作为寄存器,具体取决于优化引用类型是一种对偶值。引用类型本质上是一个指针,并且指针值遵循与值类型相同的“分配”规则,但是一旦将值存储在其中,即。对一个对象的引用,该对象在其他地方的堆上。
换句话说,引用变量本身是作为值类型“分配”的,但它所引用的对象是在堆上的。
当您从一个类构造一个对象时,会在堆上分配空间以适应该类的所有字段 + 该空间中的一些开销。
我似乎记得 Jon Skeet 有一篇关于这个主题的文章,我相信他很快就会给出答案,敬请期待。
【讨论】:
他在那里,而我正在输入答案。【参考方案3】:这比您想象的要复杂。即使您声称“在堆栈上分配值类型”也不正确。例如:
class Foo
int x;
int
是一个值类型,但 x 的值将始终在堆上,因为它将与类 Foo 实例的其余数据一起存储。
此外,匿名函数和迭代器块的捕获变量使生活变得更加棘手。
我有一个article about C# heap/stack memory,您可能会觉得有用,但您可能还想阅读 Eric Lippert 在"The stack is an implementation detail" 上的博客文章。特别是,未来的 C# 编译器可以决定将其所有局部变量存储在堆上,使用堆栈来保存对在方法开始时创建的实例的引用......这不会违反 C# 规范全部。
【讨论】:
【参考方案4】:这篇文章看起来很先进,但又不过分。它应该可以让您更好地理解:
http://www.simple-talk.com/dotnet/.net-framework/understanding-garbage-collection-in-.net/
【讨论】:
【参考方案5】:当一个方法被调用时,值类型所需的空间量是预先知道的(它可以由编译器计算出来)。该空间在堆栈上分配,并且仅在方法调用期间可用。对于每个新方法调用,堆栈上使用的内存都会增长,而当方法退出时,它会缩小到之前的级别。
引用类型在堆上分配。堆基本上是用于该目的的一块内存。存储在堆上的对象主要是存储在分配给对象的内存中的对象的字段。因此,值类型字段存储在堆上的对象“内部”。引用类型字段存储为对被引用对象的引用(或指针)。堆上的内存由垃圾回收管理。这是一个复杂的主题,但简短的故事是分配给堆上未使用对象的内存被释放,因此有资格被垃圾收集器定期重用。
【讨论】:
以上是关于.net 框架中值类型和引用类型的内存分配的主要内容,如果未能解决你的问题,请参考以下文章