如何检测或避免使用std :: shared_ptr的循环引用?
我强烈地回应sellibitze所说的话,并重新考虑设计。如果你真正拥有的是单向所有权,而只是在相反的方向观察,可以考虑weak_ptr。这使您可以检查一个对象是否处于活动状态,但不会仅仅因为您有一个指向它的对象而使对象保持活动状态。
明显的答案是不要使用shared_ptr
对象,其中 本身可能包含shared_ptr
。 shared_ptr
是有点特别的,应该谨慎使用 。
您可以通过设计避免这种情况。正如Stephan T. Lavavej在GoingNative2012会议上指出的那样(您可以在线查看视频),“所有权”是一个有向非循环图,即DAG。 DAG中没有周期。如果你的所有权图不是DAG,你的设计是......可疑的,因为拥有B和B的拥有A是没有意义的。但shared_ptr是一个“共享所有者指针”。持有这种指针的对象或作用域拥有指针。尝试从所有权图的角度思考。
shared_ptr不是每个案例的正确工具。它不应该让你编写代码,就像你在Java中一样,你不必考虑所有权(很多)。它应该提供自动和确定性的清理。如果你需要一个“非拥有”指针,weak_ptr或者一个原始指针是合适的。只要确保一个原始指针指向的对象保持足够长的时间。
Java仍然没有确定性的对象破坏。 Java确实使用(){}构造支持像C#这样的构造,但这远离C++对象销毁提供的确定性。 – Unknown1987 2012-02-23 23:29:40
我没有声称Java确实有对象破坏。 – sellibitze 2012-02-24 11:12:36
你可以实现一个,就像创建this
指针(例如通过宏)的smart_ptr
上的包装一样。然后建立带有从存储的this
到shared_ptr
包含的对象的边的有向图并检测任何周期,例如,通过拓扑排序。
我会推荐这只适用于密集的shared_ptr
使用和无法控制所有设计方面的大型代码库。对于其他情况只需使用@sellibitze建议。
我没有设计来重新思考。我想知道如何设计,所以我没有这个问题。 – 2012-02-23 19:23:16
没有进一步的背景,不可能推荐如何构建关系。我会考虑谁拥有谁的问题。如果你最终的模型是一个意大利面杂乱的指针太难以保持所有权明确定义,显然这不是一个设计良好的模块。将问题分解为更小的块,以便将其封装。通过这种方式,您可以构建足够简单的所有权层次结构。 – Unknown1987 2012-02-23 23:25:25