2

当我阅读下一本书“值和引用类型”一章时,我想到了一个问题:“值类型何时存储在堆栈中”?原因程序员无法在类外初始化任何值类型。因为当我们在类中初始化一些值类型的变量时,变量存储在堆中。

我的问题是:值类型何时存储在堆栈中?

4

5 回答 5

11

嗯,首先你很少需要知道,但基本上,值类型存储在它们所拥有的任何地方

当它们是线程执行流程的一部分时,它们会存储在堆栈中,这可能意味着:

  • 在“本地”(方法变量)中 - 不包括某些情况(如下)
  • 作为方法的一部分中的浮点值,即将作为值传递给另一个方法的一个方法的返回值 - 不涉及“本地”,但该值仍在堆栈上
    • 按值传递的值类型参数(即没有refor out)只是这种情况的一个特例
  • 在一个实例“字段”(一个类型变量)上另一个本身在堆栈上的值类型(出于上述原因)

它们在以下情况下存储在堆中(作为对象的一部分):

  • 在类的实例“字段”中
  • 在本身位于堆上的值类型上的实例“字段”中
  • 在一个静态的“领域”
  • 在一个数组中
  • 在作为迭代器块、异步方法的一部分的“本地”(方法变量)中,或者是 lambda 或匿名方法中的“捕获”变量(所有这些都会导致本地被提升到由编译器生成的类)
  • 当“装箱”时 - 即转换为引用类型(object, dynamic, Enum, ValueType(是的:ValueType是引用类型;有趣,嗯?)ISomeInterface,等等)
于 2013-08-22T09:13:18.720 回答
3

我的问题是:值类型何时存储在堆栈中?

关于值类型的真相

[I]在桌面CLR上的C#微软实现中,当值是局部变量或临时值而不是lambda或匿名方法的封闭局部变量时,值类型存储在堆栈中,并且方法体不是迭代器块,并且抖动选择不注册该值

于 2013-08-22T09:12:17.950 回答
0

准确地说,堆栈和堆在托管环境中是(或应该是)不相关的

在实践中,局部变量值类型(C# 中的结构)倾向于在堆栈上分配。但是,在某些情况下,它们被分配在堆上

一种这样的情况是当它们被装箱时。装箱意味着使用 anInt32作为Object,例如通过将其传递给采用object参数的方法。造成这种情况的一个原因是多态性:结构不携带 vTable 指针,因此不能进行动态虚拟方法解析(例如ToString(),对于诸如 的方法) - 但它们是密封的,因此它们可以静态进行解析。另一方面,如果一个结构被强制存储在一个object引用中,它需要被转换为一个堆分配的支持 vTable 的对象。

当它是堆分配对象的一部分时,也可以在堆中分配值类型- 例如,当它是类的数据成员(字段)时。

于 2013-08-22T09:10:29.293 回答
0

另一个混淆来源似乎是您假设引用类型和值类型是两种类型的类,这是不正确的

关键字class-> 引用类型
关键字struct-> 值类型

于 2013-08-22T09:10:49.897 回答
0

对您的问题的第一次网络搜索为您提供 Eric Lippert 的The Truth About Value Types,它从最重要的部分开始:它几乎总是无关紧要的。那么,你为什么想知道?你会以不同的方式编程吗?

反正:

事实是:分配机制的选择只与存储所需的已知生命周期有关。

于 2013-08-22T09:12:34.137 回答