我有些困惑的是,在C#中只有引用类型才会被垃圾回收。 这意味着GC只选取引用类型进行内存释放。 那么值类型会怎样,因为它们也占据栈上的内存空间?
我有些困惑的是,在C#中只有引用类型才会被垃圾回收。 这意味着GC只选取引用类型进行内存释放。 那么值类型会怎样,因为它们也占据栈上的内存空间?
我对一个事实感到有些困惑,即在C#中仅有引用类型会被垃圾回收。
这不是一个事实。或者说,这个说法的真假取决于你所指的“被垃圾回收”。垃圾回收器当然会检查值类型进行回收;这些值类型可能仍然存活并持有一个引用类型:
struct S { public string str; }
...
S s = default(S); // local variable of value type
s.str = M();
当垃圾回收器运行时,它确实会查看变量 s,因为它需要确定 s.str 仍然存在。我的建议是:要准确地说明“被垃圾回收”这个动词的意思。
GC仅选择引用类型进行内存释放。
同样,这不是事实。假设你有一个实例:
class C { int x; }
整数的内存将位于垃圾回收堆上,并且在C实例未被引用时被垃圾回收器回收。
为什么您认为只有引用类型的内存才由垃圾回收器释放是错误的?正确的说法是,由垃圾回收器分配的内存将由垃圾回收器进行释放,这我认为是非常合理的。 因为垃圾回收器分配了它,所以它也负责清理。
那么值类型会怎样,因为它们也在堆上占用内存?
对它们什么都不会发生。 对它们没有任何要求。 栈大小为100万字节。 栈的大小在线程启动时确定; 它从一百万字节开始,并在整个线程执行过程中保持不变。 栈上的内存既不会被创建也不会被销毁; 只有其内容被更改。
return
语句。此时,堆栈指针被恢复到其原始值。实际上,它“忘记”了本地变量的存在。它们的值没有以任何方式被“擦除”,字节仍然存在。但它们不会持续很久,你程序中的下一个调用将再次覆盖它们。CLR的零初始化规则确保你永远无法观察到那些旧值,否则会存在安全隐患。当值类型在作用域之外时,从堆栈中移除。
值类型在超出其作用域时立即被销毁。
值类型在执行后,当堆栈帧被移除时会被释放,我想是这样的。
.NET 中的每个值类型实例都将成为其他东西的一部分,这可能是一个更大的封闭值类型实例、堆对象或堆栈帧。无论何时,任何这些东西出现时,其中的任何结构也将随之出现;只要包含它们的东西存在,这些结构就会继续存在。当包含结构的东西停止存在时,结构也将停止存在。没有办法摧毁一个结构而不摧毁容器,也没有办法摧毁包含一个或多个结构的东西而不摧毁其中包含的结构。