【问题标题】:How is value type array allocated in a heap?如何在堆中分配值类型数组?
【发布时间】:2019-02-24 21:44:54
【问题描述】:

我阅读了一些类似问题的答案,但我的问题略有不同,因为我不理解书中关于此问题的陈述。

因为结构体是值类型,所以每个实例不需要 堆上对象的实例化;这会带来有用的节省 在创建一个类型的许多实例时。例如,创建一个 值类型的数组只需要一个堆分配。

我的意思是数组如何只需要一个堆分配?...或者说单个堆分配是什么意思

【问题讨论】:

  • 您在该声明中具体有哪些不明白的地方?
  • 数组只是堆上的一块内存。如果它包含一个值类型,那么这就是那个内存块中的内容。如果它有引用类型,那么那些指向堆中其他位置的对象。
  • 我的意思是数组如何只需要单个堆分配?...或者单个堆分配是什么意思
  • “单个 hep 分配”是指堆上的单个连续内存块。
  • 你熟悉C还是C++?

标签: c# arrays struct heap-memory value-type


【解决方案1】:

首先,让我们澄清一下“堆”与“堆栈”的含义。

当今的大多数编程环境都是基于堆栈的。运行程序时,每次调用方法时,都会将新条目推送到为程序提供的特殊堆栈中。这个堆栈条目(或帧)告诉系统在哪里寻找方法的可执行代码,传递了哪些参数,以及方法退出后调用代码中返回的确切位置。当一个方法完成时,它的条目会从堆栈中移除(弹出),因此程序可以返回到前一个方法。当堆栈为空时,程序结束。

堆栈上的每一帧也有一定的空间用于方法的局部变量,堆栈本身的大小是有限的。这就是“堆栈溢出”的来源。方法调用过深,栈空间不足。

另一方面,堆是不会自动授予程序的内存。它是程序必须在其核心分配之外请求的内存。堆内存必须更仔细地管理,但(通常)还有更多可用空间。因为它必须由操作系统根据请求授予,所以来自堆的初始分配也比来自堆栈的分配慢一些。

作为一个广义的概括,我们说引用类型在堆上分配,而值类型在堆栈上分配(尽管有很多例外)。

现在我们了解了这么多,我们可以开始看数组了。

核心数组类型本身是一个引用类型。我的意思是,对于任何给定类型TT 可能(或可能不是)值类型,但@ 987654324@ 始终是引用类型。在“堆栈与堆”上下文中,这意味着创建一个新数组是一个堆分配,即使T 是一个值类型。数组也有固定的大小。该单一堆分配将为数组中的所有元素创建足够的空间。

值类型的另一个特性是它们具有基于成员的固定大小。所以对于一个数组,我们有固定数量的元素,每个元素都有一个已知的固定大小。这些信息足以在单个堆分配中为数组对象 及其元素 获取所有空间。每个项目的 都保存在数组的核心内存中。

对于保存引用类型的数组,数组的堆分配只为引用创建空间。要填充数组,您必须为每个元素进行额外分配。

对于具有一个或多个引用类型成员的值类型,这可能会稍微复杂一些。在这种情况下,值类型的空间是正常分配的,但引用成员的值部分只是一个引用。它仍然需要单独分配来为这些引用成员创建对象。

【讨论】:

  • 不知道为什么这被否决了。如果有人认为我对这些概念的理解有缺陷,我很乐意纠正它。
  • 我不是反对者。虽然我喜欢你的回答,但我建议你添加一个指向 Eric Lippert 的关于值类型与引用类型的博客的链接,你说“尽管有很多例外”。 blogs.msdn.microsoft.com/ericlippert/2010/09/30/…
  • @Joel Coehoorn 非常感谢您的回答。这么透彻的解释。我明白你在解释什么。
  • @Jim Mischel,感谢您的链接,我也会通过它。
【解决方案2】:

数组本身就是一个引用类型,也就是说,它是在托管堆上分配的。但是,如果它是一个值类型的数组,它会在一个步骤中保留其大小所需的内存。让您拥有一个包含 4 个 Int32 的结构。

A struct4Int[1000] will allocate 16000 bytes in one step.

引用类型的数组将只占用引用所需的内存(每个项目 32 位或 64 位,具体取决于您正在编译的体系结构)。让我们说一个有 4Int32 的类。

A class4Int[1000] will allocate 4000 or 8000 bytes at first.

item 用引用的地址填充,初始为空。

创建数组后,您必须为引用类型的每个实例分配内存并将其引用放入数组中(堆上的多个分配),在堆上以 1000 个小块再添加 16000 个字节。

【讨论】:

    猜你喜欢
    • 2018-01-06
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 2015-07-26
    • 2017-06-25
    • 2021-02-24
    相关资源
    最近更新 更多