如何在使用shared_ptr时检测周期

Unk*_*own 21 c++ garbage-collection reference-counting shared-ptr

shared_ptr是Boost库中的引用计数智能指针.

引用计数的问题在于它不能处理循环.我想知道如何用C++解决这个问题.

请不要这样的建议:"不要制作周期",或"使用weak_ptr".

编辑

我不喜欢只使用weak_ptr的建议,因为很明显,如果你知道你会创建一个循环,那么你就不会有问题.如果在运行时生成shared_ptrs,您也无法知道编译时会有一个循环.

所以,请自行删除使用weak_ptr的答案,因为我特别要求不要那些答案......

n0r*_*0rd 25

shared_ptr代表所有权关系.虽然weak_ptr代表着意识.有几个对象拥有互相意味着你必须与建筑,这是通过改变一个或多个亟待解决的问题自己的成知道的(也就是weak_ptr"S).

我不明白为什么建议weak_ptr被认为是无用的.

  • 如果您可以提前知道将有一个静态所有者,auto_ptr就足够了,您不需要shared_ptr.我一直认为shared_ptr是"最后一个,关灯"的机制. (2认同)

小智 18

我明白你因为被告知要使用weak_ptr来打破循环引用和我自己的烦恼,当我被告知循环引用是糟糕的编程风格时,我几乎感到愤怒.

您具体询问如何发现循环引用.事实是,在一个复杂的项目中,一些参考周期是间接的,很难发现.

答案是你不应该做出虚假声明,使你容易受到循环引用的攻击.我是认真的,我批评一个非常流行的做法 - 盲目地使用shared_ptr来做所有事情.

您应该在设计中清楚哪些指针是所有者,哪些是观察者.

对于所有者使用shared_ptr

对于观察者来说,使用weak_ptr - 所有这些,不仅仅是你认为可能属于周期的那些.

如果您遵循这种做法,那么循环引用不会引起任何问题,您不必担心它们.当然,当你想要使用它们时,你需要编写很多代码来将所有这些weak_ptrs转换为shared_ptrs - Boost确实无法胜任工作.


小智 5

检测周期相当容易:

  • 将计数设置为较大的数字,例如 1000(确切大小取决于您的应用程序)
  • 从您感兴趣的指针开始并按照它的指示进行操作
  • 对于您跟随的每个指针,递减计数
  • 如果在到达指针链末尾之前计数下降到零,则有一个循环

然而,它不是很有用。并且通常不可能解决引用计数指针的循环问题 - 这就是发明替代垃圾收集方案(如代清除)的原因。

  • 这似乎不是一个正确的答案。答案不会“检测”循环,而是算法只是说“代码中*可能*存在循环”。 (2认同)

pet*_*hen 4

我还没有找到比绘制大型 UML 图并寻找循环更好的方法。

为了进行调试,我使用一个进入注册表的实例计数器,如下所示:

template <DWORD id>
class CDbgInstCount
{
public:
#ifdef _DEBUG
   CDbgInstCount()   { reghelper.Add(id, 1); }
   CDbgInstCount(CDbgInstCount const &) {  reghelper.Add(id, 1); }
   ~CDbgInstCount()  { reghelper.Add(id, -1); }
#else
#endif
};
Run Code Online (Sandbox Code Playgroud)

我只需将其添加到相关类中,然后查看注册表。

(ID,如果给定为“XYZ!”,将被转换为字符串。不幸的是,您不能指定字符串常量作为模板参数)


归档时间:

查看次数:

6589 次

最近记录:

8 年,5 月 前