【问题标题】:How is an array of value types stored in .NET object heap?值类型数组如何存储在 .NET 对象堆中?
【发布时间】:2011-07-02 13:25:42
【问题描述】:

在 .NET 中,值类型对象(例如 int)存储在内存中。

引用类型对象需要为引用和对象分别分配内存,并且对象存储在 .NET 对象堆中。

而Array是在堆中创建的,那么int[]等值类型的数组如何存储在堆中呢?是不是意味着值类型的对象可以不用装箱就可以存放在堆中?

【问题讨论】:

  • 我会说一切都存储在“内存”中(嗯......除了可能没有真正存储的常量和优化为无用或常量的变量)。您只能谈论内存的“类型”(寄存器/RAM/磁盘,仅谈论可直接访问的内存,因此跳过缓存)或其组织(堆栈,堆,???):-)您可能的意思“堆栈内存”,但正如您所发现的那样,这是错误的。
  • '值类型对象,例如 int 存储在内存中'听起来有点误导我。堆——当然——也只是一种内存.. ?

标签: c# .net heap-memory


【解决方案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 对象中(尽管它不是这样称呼的)。

    实际上并没有要求值类型在放入堆之前必须被装箱。您可以通过三种方式将值类型放在堆上:

    1. 通过将其包装在常规对象中。

    2. 通过拳击。

    3. 通过将其包装在数组对象中。

    可能有更多方法,但我认为我没有错过任何方法。)

    【讨论】:

      【解决方案4】:

      这样想,对象在内存中的位置是由它的类型和声明的位置来定义的。如果对象是值类型,则其 value 存储在您声明变量的位置。如果对象是引用类型,则它的 reference 存储在您声明变量的位置,而实际的对象实例存在于堆中。

      当您声明一个局部变量时,您就是在堆栈上声明该变量。因此,值类型的值将在堆栈上。引用类型的引用将在堆栈上,而对象实例仍在堆上。

      如果您在类中声明实例变量(引用类型),则实际上是在堆中声明实例变量。值类型的值将在堆中(在对象实例中)。引用类型的引用也将在堆中(在对象实例中),对象实例将在堆中的其他位置。

      如果您在结构(值类型)中声明实例变量,它所在的位置取决于底层结构的声明位置。

      对于 int int[] 数组,数组是引用类型,您可以将 int 值视为该类型的“字段”,因此您的整数实际上位于堆中。

      【讨论】:

        猜你喜欢
        • 2011-06-11
        • 1970-01-01
        • 2011-04-21
        • 2014-04-18
        • 2021-06-19
        • 2013-08-24
        • 2020-08-24
        • 1970-01-01
        • 2014-03-19
        相关资源
        最近更新 更多