堆
stack
是用于存储local variables
和的内存块parameters
。随着函数的进入和退出,堆栈在逻辑上会增长和缩小。
考虑以下方法:
public static int Factorial (int x)
{
if (x == 0)
{
return 1;
}
return x * Factorial (x - 1);
}
此方法是递归的,这意味着它会调用自身。每次进入方法时,都会在堆栈上分配一个新的 int,每次方法退出时,都会释放 int。
堆
- 堆是
objects
(即reference-type instances
)驻留的内存块。每当创建一个新对象时,它都会在堆上分配,并返回对该对象的引用。在程序执行期间,随着新对象的创建,堆开始填满。运行时有一个垃圾收集器,它会定期从堆中释放对象,因此您的程序不会运行Out Of Memory
。一个对象只要没有被任何本身引用的对象就可以被释放alive
。
- 堆还存储
static fields
. 与在堆上分配的对象(可以被垃圾回收)不同,these live until the application domain is torn down
.
考虑以下方法:
using System;
using System.Text;
class Test
{
public static void Main()
{
StringBuilder ref1 = new StringBuilder ("object1");
Console.WriteLine (ref1);
// The StringBuilder referenced by ref1 is now eligible for GC.
StringBuilder ref2 = new StringBuilder ("object2");
StringBuilder ref3 = ref2;
// The StringBuilder referenced by ref2 is NOT yet eligible for GC.
Console.WriteLine (ref3); // object2
}
}
在上面的例子中,我们首先创建了一个由变量 ref1 引用的 StringBuilder 对象,然后写出它的内容。然后该 StringBuilder 对象立即有资格进行垃圾收集,因为随后没有人使用它。然后,我们创建另一个由变量 ref2 引用的 StringBuilder,并将该引用复制到 ref3。即使 ref2 在那之后不再使用,ref3 也会保持同一个 StringBuilder 对象处于活动状态——确保在我们使用完 ref3 之前它没有资格被收集。
值类型实例(和对象引用)存在于声明变量的任何地方。如果实例被声明为类类型中的字段或数组元素,则该实例位于堆上。