值类型数组如何存储在 .NET 对象堆中?
Posted
技术标签:
【中文标题】值类型数组如何存储在 .NET 对象堆中?【英文标题】:How is an array of value types stored in .NET object heap? 【发布时间】:2011-07-02 13:25:42 【问题描述】:在 .NET 中,值类型对象(例如 int)存储在内存中。
引用类型对象需要为引用和对象分别分配内存,并且对象存储在 .NET 对象堆中。
而Array是在堆中创建的,那么int[]等值类型的数组如何存储在堆中呢?是不是意味着值类型的对象可以不用装箱就可以存放在堆中?
【问题讨论】:
我会说一切都存储在“内存”中(嗯......除了可能没有真正存储的常量和优化为无用或常量的变量)。您只能谈论内存的“类型”(寄存器/RAM/磁盘,仅谈论可直接访问的内存,因此跳过缓存)或其组织(堆栈,堆,???):-)您可能的意思“堆栈内存”,但正如您所发现的那样,这是错误的。 '值类型对象,例如 int 存储在内存中'听起来有点误导我。堆——当然——也只是一种内存.. ? 【参考方案1】:是的,你是对的。我建议您阅读以下内容:
https://ericlippert.com/2010/09/30/the-truth-about-value-types/
非常非常好,它解释了几乎所有你想知道的东西。
【讨论】:
是这种情况吗,几乎所有时间,所有值类型都将存储在 HEAP 上 - 所有实例变量都将存储在 HEAP ...,这是正确的理解吗?【参考方案2】:是的,数组是一种一种可以将值类型值存储在堆上而无需装箱的方式。另一个只是在普通课程中使用它:
public class Foo
int value1;
string name;
// etc
与Foo
实例关联的所有变量都存储在堆上。 value1
的值就是int
,而name
的值是一个字符串引用。
这就是为什么“值类型存储在堆栈上,引用类型存储在堆上”的说法显然是错误的。
但是,由于 Eric Lippert 是 rightly fond of pointing out,堆栈/堆的区别是一个实现细节。例如,CLR 的未来版本可以将一些对象存储在堆栈上,前提是在方法终止后不再需要这些对象。
【讨论】:
【参考方案3】:是的,这意味着没有对到达元素进行装箱,因为整个数组作为一个整体被“装箱”在一个 Array 对象中(尽管它不是这样称呼的)。
实际上并没有要求值类型在放入堆之前必须被装箱。您可以通过三种方式将值类型放在堆上:
通过将其包装在常规对象中。
通过拳击。
通过将其包装在数组对象中。
(可能有更多方法,但我认为我没有错过任何方法。)
【讨论】:
【参考方案4】:这样想,对象在内存中的位置是由它的类型和声明的位置来定义的。如果对象是值类型,则其 value 存储在您声明变量的位置。如果对象是引用类型,则它的 reference 存储在您声明变量的位置,而实际的对象实例存在于堆中。
当您声明一个局部变量时,您就是在堆栈上声明该变量。因此,值类型的值将在堆栈上。引用类型的引用将在堆栈上,而对象实例仍在堆上。
如果您在类中声明实例变量(引用类型),则实际上是在堆中声明实例变量。值类型的值将在堆中(在对象实例中)。引用类型的引用也将在堆中(在对象实例中),对象实例将在堆中的其他位置。
如果您在结构(值类型)中声明实例变量,它所在的位置取决于底层结构的声明位置。
对于 int int[]
数组,数组是引用类型,您可以将 int
值视为该类型的“字段”,因此您的整数实际上位于堆中。
【讨论】:
以上是关于值类型数组如何存储在 .NET 对象堆中?的主要内容,如果未能解决你的问题,请参考以下文章