29

我昨天看到一个问题(对我来说)提出了另一个问题。请看下面的代码:

public class Class1
{
   int A; //as I uderstand, int is value type and therefore lives in the stack
}

class Class2
{
    Run()
   {
       Class1 instance1 = new Class1();
       instance1.A = 10;  //it points to value type, but isnt this reference (on heap)?
   }
}

或者在创建 Class1 的实例时,它的字段类型也是在堆上创建的?但是我不明白它什么时候会真正在堆栈上,因为几乎总是需要创建一个对象实例才能使用它的字段。

4

3 回答 3

53

据我了解, int 是值类型,因此存在于堆栈中

你的理解是不正确的。值类型被称为“值类型”,因为它们是按值复制的。引用类型被称为“引用类型”,因为它们是通过引用复制的。“值类型总是存在于堆栈中”这一说法根本不正确。如果这是真的,它们将被称为“堆栈类型”和“堆类型”。

事实是,这是一个实现细节。不同的框架实现可以随意选择使用栈和堆。以下是 Microsoft 实现的方式:

  • 引用类型变量的值是对堆内存的引用。引用基本上是一个 32 位或 64 位整数。
  • 值类型变量的值就是它的值。
  • 局部变量的值存储在堆栈中,除非局部变量在迭代器块中或者是匿名方法或 lambda 表达式的封闭外部变量。在这些情况下,局部变量的值存储在堆上。当然,除非局部变量可以被优化掉,在这种情况下根本没有存储空间。或者也许它们可以被注册,在这种情况下它们既不在堆栈也不在堆上,它们在处理器寄存器中。
  • 引用类型的实例变量和静态变量的值存储在堆上。

明白了吗?

它指向值类型,但不是这个引用(在堆上)吗?

字段“A”是值类型。它是一个字段,因此该变量存储在堆上。

在创建 Class1 的实例时,它的字段类型也是在堆上创建的吗?

实例变量的存储在堆上,是的。

但是我不明白它什么时候会真正在堆栈上,因为几乎总是需要创建一个对象实例才能使用它的字段。

它永远不会在堆栈上。正如我上面所说,堆栈上唯一的东西是局部变量(和编译器生成的临时变量),它们不是 lambda 或匿名方法的封闭局部变量,也不在迭代器块中。当然,如果有空闲寄存器,抖动是自由的,可以让它们完全脱离堆栈并将它们放入寄存器中。

但实际上,我不得不问,你为什么关心堆栈上的内容和堆上的内容?堆栈上的东西是我们可以廉价放入堆栈的东西;其他一切都在堆上。

于 2010-04-02T15:05:35.320 回答
9

局部结构(值类型)变量存储在堆栈中,类的值类型字段存储在堆中。

于 2010-04-02T06:35:22.053 回答
2

好的 int 是一个值类型,但 '1'(一个类的名字太糟糕了)是一个引用类型。这意味着“1”的任何实例都在堆上。

于 2010-04-02T06:35:34.937 回答