值类型会被垃圾回收吗?

24

我知道引用类型会被进行垃圾回收。我想知道在堆栈中的值类型是否也会被垃圾回收?


你能仔细地定义一下“垃圾回收”对你来说意味着什么吗? - Eric Lippert
我的意思是"垃圾收集",也就是说,如果应用程序发现一个值类型变量没有被使用,那么它将从栈中删除。 - csharpbaby
我认为Eric已经解释得非常清楚了,但是为了确保,让我更直接地回答一下:局部变量将保持分配状态,只要它在作用域内,无论是否有其他东西引用它。它不受收集的影响,只受作用域的限制。 - Steven Sudit
3个回答

40
很难理解您的问题的意思。能否仔细定义一下“垃圾收集”是什么意思?它是指“作为GC算法的输入”,还是指“通过压缩GC堆进行释放”或其他?
存储在堆栈上的值,无论是值类型还是引用类型的值,都是收集算法的“根”。它们“不会被收集”,因为它们是活着的东西,几乎保持了其他所有东西的活性。
显然,它们不会通过压缩GC堆来释放;它们会通过从堆栈中弹出它们来释放。
这回答了您的问题吗?
更新:
我所说的“垃圾收集”是指,如果一个值类型变量未被应用程序使用,则它将从堆栈中移除。
好的,我想我们离一个可以回答的问题更近了。现在我们需要理解您所说的“从堆栈中移除”的确切含义。
堆栈是预分配的内存块,大小为一百万字节。有时我们使用该内存块的一部分来存储值类型的本地变量。您所说的“从堆栈中移除”具体是什么意思?堆栈的大小始终不变;它是一个预分配的一百万字节内存块。
堆栈分为两个相邻的区域,我们将其称为“有效”和“无效”的堆栈部分。在x86架构中,ESP寄存器指向这些区域之间的边界。您是否想知道“在x86架构中,与堆栈上特定值类型本地变量关联的内存何时基于ESP寄存器值的更改成为无效堆栈部分的一部分?”?

这似乎是你问题的一个非常, 非常 "具体实现细节" 的版本。 堆栈是特定版本运行时的实现细节,因此如果您要询问有关它的问题,您必须接受这样一个事实:您正在询问特定芯片架构上特定寄存器中的特定值。

进一步阅读:

References are not addresses

The Stack Is An Implementation Detail, Part One

The Stack Is An Implementation Detail, Part Two

“Out Of Memory” Does Not Refer to Physical Memory

现在我有点困惑于你提到的“值”和“值类型”。我发现很难理解它们之间的区别。

这很棘手!我们用“值”和“引用”这些词来表示太多的事情。让我总结一下。

变量是一个存储位置

每个变量都有一个类型。类型可以是值类型引用类型

存储位置包含一个

值类型变量的值是值类型的值。例如,int是一个值类型。类型为int的变量的值是int,比如12。

引用类型的变量值是指向该类型对象的引用,或者是null。例如,string是一个引用类型。类型为string的变量值是指向字符串的引用,或者是null。

这就是为什么它们被称为“值类型”和“引用类型”的原因。 值类型的值是该类型的实例。 引用类型的值是指向该类型实例的引用。

现在是否清晰明了呢?


谢谢。这样解释清楚了我的所有疑问 :-). 感谢您这个出色的解释。(附言:我是您的超级粉丝,我通过分享您博客中的知识,给我的朋友留下了深刻的印象!) - csharpbaby
@csharpbaby:不用谢。我在上面的文本中放了一些你可能会感兴趣的博客文章链接。 - Eric Lippert

10

4
值类型不一定存储在堆栈上。正确的说法是,“值类型的值如果是临时储存或者本地变量,且不是匿名方法或lambda表达式的闭包本地变量,也不在一个迭代器块中,那么在Microsoft CLI的实现中将存储在堆栈上。” 一个不在GC堆上的值类型不会被垃圾回收器清理。而一个在GC堆上的值类型则会被垃圾回收器清理。 - Eric Lippert
1
+1 同意,但是试图将其转化为一个清晰简洁且易于理解的答案是一项挑战;-) - Russell Giddings
你说得对。我想在Eric写了“值类型的值”之后,我现在正在非常努力地思考。 :) - csharpbaby
我刚刚更新了我的第二个链接,它有一个非常好的深入解释,配有很多图表(如果您和我一样,这些图表可以帮助您很多!):-) - Russell Giddings

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接