对scoped_ptr的弱引用

Weak reference to a scoped_ptr?

本文关键字:引用 ptr scoped      更新时间:2023-10-16

一般来说,我遵循谷歌风格指南,我觉得这与我看待事物的方式非常一致。我还几乎专门使用boost::scoped_ptr,以便只有一个管理器拥有特定对象的所有权。然后我传递裸指针,我的想法是,我的项目的结构是这样的,即所述对象的管理器总是在使用它们的对象被销毁后被销毁。

http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml Smart_Pointers

这一切都很好,但是我刚刚被一个讨厌的小内存踩踏bug咬了一下,在使用它的对象被删除之前,所有者恰好被删除了。

现在,在每个人都认为我是这个模式的傻瓜之前,我为什么不直接使用shared_ptr呢?等等,考虑我不想有未定义的所有者语义这一点。尽管shared_ptr会捕捉到这种特殊情况,但它会向系统用户发送错误的消息。上面写着:"我不知道这是谁的,可能是你!"

如果是指向作用域指针的弱指针,那就对我有帮助了。实际上,这是一个具有弱引用列表的作用域指针,当作用域指针销毁时,这些引用将被清空。这将允许单一所有权语义,但给使用对象一个机会来捕捉我遇到的问题。

因此,以额外的'weak_refs'指针用于scoped_ptr和'next_weak_ptr'的额外指针为代价,它将创建一个整洁的小单所有者,多用户结构。

它甚至可能只是一个调试特性,所以在'release'中,整个系统只是变成一个正常大小的scoped_ptr和一个标准的弱引用单指针。

所以…我的问题是:

  1. 是否有这样的指针/模式已经在stl/boost,我是失踪了,还是我该自己卷?
  2. 有更好的方法吗仍然满足我的单一所有权目标?

欢呼,Shane

2。有没有更好的方法,既能满足我的单一所有权目标?

使用shared_ptr,但作为类成员,使其成为该类不变量的一部分,并且公共接口只公开获取weak_ptr的方法。

当然,病理代码可以从weak_ptr中保留自己的shared_ptr,只要他们想要。在这里,我不建议你去对抗马基雅维利,我只建议你去对抗墨菲(借用萨特的话)。另一方面,如果您的用例是异步的,那么锁定weak_ptr返回shared_ptr的事实可能是一个特性!

虽然shared_ptr会捕捉到这种特殊情况,但它会向系统的用户发送错误的消息。上面写着:"我不知道这是谁的,可能是你!"

shared_ptr并不意味着"我不知道谁拥有这个"。它的意思是"我们拥有这个。"仅仅因为一个实体没有独占所有权并不意味着任何人都可以拥有它。

shared_ptr的目的是确保在共享该指针的所有人都同意销毁该指针之前,该指针不会被销毁。

是否有这样一个指针/模式已经在stl/boost,我错过了,或者我应该只是滚动我自己的?

可以像使用scoped_ptr一样使用shared_ptr。仅仅因为它可以被分享,并不意味着你有可以分享。这是最简单的工作方式;让单一所有权成为惯例,而不是api建立的规则。

然而,如果你需要一个单所有者的指针,但是有弱指针,Boost中没有。

我不确定弱指针会有多大帮助。通常,如果组件X使用另一个组件Y, X必须被告知Y的消亡,不仅仅是使指针无效,还可能将其从列表中移除,或者改变它的操作方式,使它不再需要对象。许多年前,当我第一次开始使用c++时,有一大堆活动试图找到一个良好的通用解决方案。(问题是当时称之为关系管理。)据我所知,不行找到了通用的解决方案;至少我参与的每个项目都是这样使用了一个基于观察者模式的手工构建的解决方案。

我确实在我的网站上有一个ManagedPtr,当它还在的时候,它表现得很好就像你描述的那样。在实践中,除了特别的我从来没有发现它有什么真正的用处,因为通知总是需要的。然而,这并不难实现;托管对象派生自ManagedObject类,并获得所有的指针(ManagedPtr,而不是原始指针)。指针本身注册在ManagedObject类中ManagedObject类的析构函数访问它们,并"断开连接"。通过将实际指针设置为空来获取它们。当然,还有ManagedPtr有一个isValid功能,以便客户端代码可以测试之前废弃。这很有效(不管对象是什么)管理我的大多数实体对象"拥有"自己,并做一个delete this是对某些特定输入的响应),除非您倾向于泄漏无效的ManagedPtr(例如,每当客户端保留指针时)在某种类型的容器中(因为它可能有多个容器),并且客户端仍然不会收到通知,如果他们需要采取一些行动,当您对象死亡。

如果您碰巧使用QT, QPointer基本上是指向QObject的弱指针。它将自己连接到指向值中的"I just got destroyed"事件,并根据需要自动使自己失效。这是一个非常庞大的库,可以用来跟踪bug,但是,如果您还没有跳过QT的环的话。