清空双向链表

5

我有一个自己编写的双向链表(队列)。

我想知道,要清空该链表,是否仅需删除头部和尾部引用即可?

例如:

public void Clear()
{
    Head = null;
    Tail = null;
}

我想象了一个多米诺骨牌效应,但我很难测试它。

它至少会使整个对象看起来是空的。所有数据请求(如peek、dequeue等)都返回null。

您还可以轻松地将一些新对象加入队列。

纯函数似乎是有效的。

但我真的很想知道我是否以正确的方式做到了这一点。

3个回答

7
简短的回答是,只要没有外部引用它们,垃圾回收将清除所有链表节点。最简单的测试方法是向您的链表节点对象添加终结器以输出一些日志。请注意,您无法确定垃圾收集器何时运行(除非通过GC.Collect()强制运行),因此您不会在调用Clear()方法后立即看到终结器被调用。
然而,“多米诺骨牌效应”不会发生,这并不重要的是对象是否被引用,而是引用是否可以追溯到堆栈或静态对象。因此,如果几个对象彼此引用,但没有任何东西引用它们,则它们将同时被垃圾回收。

谢谢,它讲解得很清楚。 - CasperT

4

除非集合中的对象需要被处理,并且这是集合的责任,否则您的方法可能是最好的方式。

由于对象没有根(没有实时引用),垃圾收集器可以将其回收并删除它。


问题是,这是否会在GC的一次通过中发生,还是每个“行”都需要像OP描述的那样进行单独的传递? - Matthew Scharley
谢谢你的回答,让我感到很安心。不过我会接受FacticiusVir的建议,因为他解释得更详细 :) - CasperT
2
它将在一次遍历中完成。垃圾回收不仅会删除没有活引用的对象,而且会尝试追踪引用到所谓的“根”的东西,基本上是静态变量、仍在运行的方法中的局部变量等。如果一个长链没有这样的根引用,整个链可以在同一遍历中被收集。 - Lasse V. Karlsen

2

我正在想象多米诺骨牌效应

这不是GC的工作方式。

GC首先标记所有“死亡”的内容,然后从根对象开始遍历所有被它们引用的对象,将每个对象标记为“活动的”。

由于您的列表不再被任何根对象(或其子对象)引用,因此它将被标记为“死亡的”。

第二轮清理将释放“死亡”对象。

我不相信您可以在finalizer中假设列表两侧的任何对象都没有被先收集,即它将按照GC自己的顺序而不是列表的顺序进行处理。

这里提供更多详细信息:http://msdn.microsoft.com/en-us/magazine/bb985010.aspx


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