2011-01-11 87 views
12

共享指针(例如boost :: shared_ptr或新的std :: shared_ptr)和垃圾收集方法(例如在Java或C#中实现的方法)之间有什么区别?我理解它的方式是,共享指针记录变量指向资源的次数,并在计数达到零时自动破坏资源。然而,我的理解是垃圾收集器也管理内存资源,但需要额外的资源来确定对象是否仍然被引用,并且不一定会立即破坏资源。垃圾收集与共享指针

我在我的假设中是否正确,并且在使用垃圾收集器和共享指针之间还有其他区别吗?另外,为什么有人会使用垃圾收集器来处理共享指针,如果他们执行类似的任务,但具有不同的性能数据?

+1

使用共享指针**是一种垃圾收集技术。至少作为第一步,许多垃圾收集器实施引用计数。 – 2011-01-11 22:29:25

回答

12

正如您所指出的,主要区别在于资源何时被释放/销毁。

GC可能派上用场的一个好处是如果你的资源需要很长时间才能发布。对于短的程序生命周期,最好让资源悬而未决并最终清理它们。如果达到资源限制,则GC可以采取行动释放其中一些资源。另一方面,共享指针在引用计数达到零后立即释放它们的资源。对于需要昂贵时间的资源的频繁采集 - 释放周期来说,这可能是昂贵的。另一方面,在一些垃圾收集实现中,垃圾收集要求整个程序暂停执行,同时检查内存,移动并释放内存。有更聪明的实现,但没有一个是完美的。

15

那些共享指针(通常称为引用计数)存在循环风险。

垃圾收集(马克和扫描)没有这个问题。

+0

你能解释一下“循环风险”是什么意思吗?你的意思是让引用计数“环绕”,因为用于保存引用计数的数据类型?或者是其他东西? – helloworld922 2011-01-11 22:59:29

+3

想象一下拿着一个ptr到B和B指向A. – 2011-01-11 23:03:33

0

在一个简单的垃圾收集系统中,没有人会持有指向任何对象的直接指针;相反,代码将持有对指向堆上对象的表项的引用。堆中的每个对象都将存储其大小(意味着所有堆对象将形成一个单链表),并在对象表中保存对象(或至少用于)的对象的反向引用。

当堆或对象表变满时,系统将在表中的每个对象上设置一个“删除我”标志。它将检查它所知道的每个对象,并且如果设置了它的“删除标记”,则取消设置并将它知道的所有对象添加到要检查的对象列表中。一旦完成,其“删除我”标志仍然设置的任何对象都可以被删除。

一旦完成,系统将从堆的开始处开始,将每个对象存储在那里,并查看其对象引用是否仍然指向它。如果是这样,它会将该对象复制到堆的开头,或者刚过最后一个复制对象的末尾;否则该对象将被跳过(并且在其他对象被复制时可能会被覆盖)。