共享指针(例如boost :: shared_ptr或新的std :: shared_ptr)和垃圾收集方法(例如用Java或C#实现的那些)之间有什么区别?我理解它的方式,共享指针跟踪变量指向资源的次数,并在计数达到零时自动销毁资源。但是,我的理解是垃圾收集器还管理内存资源,但需要额外的资源来确定对象是否仍然被引用,并且不一定会立即破坏资源。
我的假设是否正确,使用垃圾收集器和共享指针之间是否存在其他差异?另外,如果有人执行类似的任务但性能数据不同,为什么有人会在共享指针上使用垃圾收集器?
答案 0 :(得分:16)
那些共享指针(通常称为引用计数)存在循环风险。
垃圾收集(标记和扫描)没有此问题。
答案 1 :(得分:14)
正如您所指出的,主要区别在于资源被释放/销毁的时间。
GC可能派上用场的一个优点是,如果您有足够的资源需要释放。对于短暂的程序生命周期,最好让资源悬空并最终清理它们。如果达到资源限制,则GC可以采取行动释放其中一些限制。另一方面,共享指针在引用计数达到零时立即释放其资源。对于具有昂贵时间要求的资源的频繁获取 - 释放周期而言,这可能是昂贵的。
另一方面,在一些垃圾收集实现中,垃圾收集要求整个程序在检查,移动和释放内存时暂停执行。有更聪明的实现,但没有一个是完美的。
答案 2 :(得分:1)
在一个简单的垃圾收集系统中,没有人会持有任何对象的直接指针;相反,代码将保存对指向堆上对象的表条目的引用。堆上的每个对象都将存储其大小(意味着所有堆对象将形成单链接列表)以及对象表中对象的反向引用,该对象保存它(或至少用于)。
当堆或对象表变满时,系统将在表中的每个对象上设置“delete me”标志。它将检查它所知道的每个对象,如果设置了“删除标志”,则取消设置它并将它知道的所有对象添加到要检查的对象列表中。完成后,可以删除任何仍然设置了“删除我”标志的对象。
完成后,系统将从堆的开头开始,将每个对象存储在那里,并查看其对象引用是否仍然指向它。如果是这样,它会将该对象复制到堆的开头,或者只是复制到最后复制的对象的末尾;否则将跳过该对象(并且在复制其他对象时可能会被覆盖)。