换句话说,实现如何跟踪计数?
是否维护了一个类似地图的对象,所有shared_ptr
实例都可以访问该对象,其键是指针的地址,值是引用的数量?如果我必须实现shared_ptr
,这是我想到的第一个想法。
如果使用这些引用计数的智能指针,是否有可能发生内存泄漏?如果是这样,我该如何避免它们?
我已经看到了两种不同的非侵入式方法:
如果转到here并滚动到底部,则有一个很好的图表,可以更清楚地说明这些方法。
使用引用计数智能指针创建内存泄漏非常容易。只需创建在图中具有循环的对象的任何类似于图的结构。循环中的对象将防止彼此释放。这无法自动解决-例如,当您创建一个双向链接列表时,必须注意不要一次删除多个对象。
每个智能指针对象包含一个共享的引用计数-每个原始指针一个。
您可以看一下this文章。此实现将这些存储在一个单独的对象中,该对象将被复制。您也可以查看boost's documentation或智能指针上的Wikipedia article。
没有shared_ptr仅保留一个额外的指针用于引用计数。
当您复制shared_ptr对象时,它会复制带有引用计数的指针,增加它的数量,并在包含的对象上复制指针。
据我所记得,在有效C ++的一章中存在引用计数指针的问题。
原则上,您有一个“ light”指针类,其中包含一个指向包含引用的类的指针,该类知道增加/减少引用并销毁该指针对象。该引用计数类指向要引用的对象。
许多答案解决了引用计数的存储方式(对于拥有相同本机指针的所有shared_ptr,它都存储在共享内存中,但是大多数都避免了泄漏的问题。
使用引用计数的指针泄漏内存的最简单方法是创建周期。例如,保证所有指针都是带有至少两个元素的shared_ptr的双向链表不会被删除。即使释放了外部指针,内部指针仍将计数,并且引用计数将不会达到0。也就是说,至少使用最幼稚的实现。
最简单的解决循环问题的方法是将shared_ptr(引用计数的指针)与不共享对象所有权的弱指针混合在一起。
共享的指针将共享资源(指针)和其他reference_count信息。使用弱指针时,引用计数将增加一倍:有一个共享的指针引用计数和一个弱指针引用计数。每当共享指针计数达到0时,资源就被释放,但是reference_count信息将保持活动状态,直到最后一个弱指针被释放为止。]
在双向链接列表中,外部引用保存在shared_ptr中,而内部链接只是weak_ptr。只要没有外部引用(shared_ptr),列表的元素就会被释放,删除弱引用。最后,所有弱引用都已删除,指向每个资源的最后一个弱指针释放了reference_count信息。
它比上面的文字看起来少混乱,我稍后再试。
实现RC的类基本上保留对它正在管理的内存地址的引用数(来自该类的其他对象)。仅当对内存地址的引用计数为零时,才释放内存。