10

有时我真的很确定我想要指针的循环依赖,并且循环上的每个对象都应该能够使用他的指针(所以它不能是weak_ptr)。

我的问题是:这是否意味着我的设计不好?

如果我想实现图形怎么办?我可以使用智能指针吗?在图中有循环,但是对于weak_ptr,我不能使用“->”。我能做些什么?

我在 StackOverflow 上阅读了一些文章、参考资料和主题,但看起来我仍然没有得到智能指针。真的,为什么不存在一些带有“->”的weak_ptr变体?

4

3 回答 3

30

从概念方面解决这个问题,而不是实现方面。智能指针代表所有权。并且智能指针的存在不会使原始指针作为非拥有观察者的角色无效。

每个对象是否有一个明确定义的所有者(例如,一个图拥有它的所有顶点和边)?如果是这样,使用std::unique_ptr来保存图中的顶点和边,并在顶点和边内使用原始指针来相互引用。

共享所有权是否适用(例如,只要至少有一条边连接到顶点,顶点就存在)?如果是这样,则使用std::shared_ptr表示该所有权,再次使用非所有权观察者的原始指针。如果您需要相互所有权(即所有权周期),其中“只要边引用它,顶点就存在,而只要顶点引用它,边就存在”,那么 1. 仔细检查这样的设计是正确且可维护,并且 2. 如果是这样,请使用循环中的std::weak_ptr某处来打破所有权循环。你总是可以lock()aweak_ptr获得一个shared_ptr.

对于您的特定图表场景,我相信“一切都归图表所有”将是最合乎逻辑的所有权方案;但这取决于您的任务的特质。

于 2014-05-01T13:48:22.997 回答
4

您可以weak_ptr在循环中的某个地方使用;您只需将 s 提升为weak_ptrsshared_ptr即可取消引用它们。您可以通过调用weak_ptr::lock()或简单地通过传递 a weak_ptrto的构造函数来做到这一点(但请注意;如果指向的对象已被销毁shared_ptr,这将引发bad_weak_ptr异常。weak_ptr

如果你真的不能这样做(例如,如果循环中涉及的所有对象都是同一类型,这可能是你的图形示例中的情况),另一种选择是release在链中的某处放置一个函数,导致有问题的对象将其所有shared_ptrs 设置为空。

于 2014-05-01T13:38:37.600 回答
1

这是否意味着我的设计不好?

是的,但这是一个起点。

让我们考虑一些可以使用的智能指针。

unique_ptr- 存在一个负责处理对象的所有者。

shared_ptr- 存在许多(或可能有许多)所​​有者,最后一个必须处置该对象

weak_ptr- 可能存在许多所有者,但这不是其中之一,弱指针可能会在指向的对象之外存活,如果指向的对象被处置,弱指针将为空(即锁定方法将返回空 shared_ptr)

observer_ptr(n3840) - 还不是标准的一部分,因此如果需要,可以使用 C 样式指针 (T*)。这些工作与weak_ptr 非常相似,但程序员有责任确保在指向的对象被释放后所有观察者都不会被取消引用。

一种解决方案是将设计拆分为一个对象,该对象将拥有所有片段和片段(循环节点)。拥有对象可以使用shared_ptrunique_ptr自动管理节点的生命周期。节点本身可以​​使用weak_ptrobserver_ptr或引用 (Node&)相互引用

于 2014-05-02T22:10:56.107 回答