引用计数智能指针的引用计数如何工作?

问题描述 投票:29回答:7

换句话说,实现如何跟踪计数?

是否维护了一个类似地图的对象,所有shared_ptr实例都可以访问该对象,其键是指针的地址,值是引用的数量?如果我必须实现shared_ptr,这是我想到的第一个想法。

如果使用这些引用计数的智能指针,是否有可能发生内存泄漏?如果是这样,我该如何避免它们?

c++ memory-management memory-leaks smart-pointers shared-ptr
7个回答
66
投票

我已经看到了两种不同的非侵入式方法:

  1. 智能指针分配一个小内存块包含参考柜台。每个副本然后智能指针会收到一个指向实际对象的指针和一个指向引用计数的指针。
  2. 除了对象指针之外,每个智能指针都包含一个上一个和下一个指针,从而形成一个双链表指向特定对象的智能指针宾语。参考计数是隐式包含在列表中。当聪明指针被复制,它将自身添加到名单。销毁后,每个智能指针将自身从中删除名单。如果是最后一个然后释放列表以及引用的对象。

如果转到here并滚动到底部,则有一个很好的图表,可以更清楚地说明这些方法。


3
投票

使用引用计数智能指针创建内存泄漏非常容易。只需创建在图中具有循环的对象的任何类似于图的结构。循环中的对象将防止彼此释放。这无法自动解决-例如,当您创建一个双向链接列表时,必须注意不要一次删除多个对象。


3
投票

每个智能指针对象包含一个共享的引用计数-每个原始指针一个。

您可以看一下this文章。此实现将这些存储在一个单独的对象中,该对象将被复制。您也可以查看boost's documentation或智能指针上的Wikipedia article


2
投票

没有shared_ptr仅保留一个额外的指针用于引用计数。

当您复制shared_ptr对象时,它会复制带有引用计数的指针,增加它的数量,并在包含的对象上复制指针。


2
投票

据我所记得,在有效C ++的一章中存在引用计数指针的问题。

原则上,您有一个“ light”指针类,其中包含一个指向包含引用的类的指针,该类知道增加/减少引用并销毁该指针对象。该引用计数类指向要引用的对象。


2
投票

许多答案解决了引用计数的存储方式(对于拥有相同本机指针的所有shared_ptr,它都存储在共享内存中,但是大多数都避免了泄漏的问题。

使用引用计数的指针泄漏内存的最简单方法是创建周期。例如,保证所有指针都是带有至少两个元素的shared_ptr的双向链表不会被删除。即使释放了外部指针,内部指针仍将计数,并且引用计数将不会达到0。也就是说,至少使用最幼稚的实现。

最简单的解决循环问题的方法是将shared_ptr(引用计数的指针)与不共享对象所有权的弱指针混合在一起。

共享的指针将共享资源(指针)和其他reference_count信息。使用弱指针时,引用计数将增加一倍:有一个共享的指针引用计数和一个弱指针引用计数。每当共享指针计数达到0时,资源就被释放,但是reference_count信息将保持活动状态,直到最后一个弱指针被释放为止。]

在双向链接列表中,外部引用保存在shared_ptr中,而内部链接只是weak_ptr。只要没有外部引用(shared_ptr),列表的元素就会被释放,删除弱引用。最后,所有弱引用都已删除,指向每个资源的最后一个弱指针释放了reference_count信息。

它比上面的文字看起来少混乱,我稍后再试。


0
投票

实现RC的类基本上保留对它正在管理的内存地址的引用数(来自该类的其他对象)。仅当对内存地址的引用计数为零时,才释放内存。

© www.soinside.com 2019 - 2024. All rights reserved.