我正在使用 boost 共享指针,这些指针实际上在整个应用程序中共享。在某些情况下,这样的共享指针变得无效。例如,指向网络资源的共享指针可能会因为网络变得不可用而变得无效。在这种情况下,共享指针变得无效,我希望所有对象都停止使用它。如何向指针无效的所有对象发送消息。如果它是一个普通指针,我可以将它设置为 null 并且所有客户端代码都应该在使用它之前检查空指针。但是,如果是保持引用计数的共享指针,我怎样才能实现类似的功能?
5 回答
您可以使用弱指针。也就是说,处理网络事件的代码有一个,shared_ptr<Res>
而其他人都有一个weak_ptr<Res>
. 现在,
- 当资源变得不可用时,只需将 重置
shared_ptr
为NULL
; - 当客户端要使用该资源时,调用该资源
lock()
并在使用前weak_ptr
测试返回shared_ptr
是否有效。
如果它是一个普通指针,我可以将它设置为 null 并且所有客户端代码都应该在使用它之前检查空指针。
我不信。然后,您将拥有指向无效对象的原始指针的副本。你会认为这会解决问题,但事实并非如此。它放大了它。
事实是共享指针本身并不会变得无效,它包含的对象会。因此,从逻辑上讲,使用它是否仍然安全应该包含在对象中,而不是共享指针中。
指向网络资源的共享指针,由于网络变得不可用,它可能变得无效。
当您尝试调用尝试使用网络的方法时,只需抛出异常......
您需要存储更多信息。您可以将资源与元组中的 bool 放在一起,或者您可以使用boost::optional
, 并将其设置为none
当您想要使其无效时。
您几乎可以肯定不应该为此使用共享指针,因为它的语义不符合您的需要。共享指针实现了一种穷人的垃圾收集,当没有更多指向它的指针时,对象不再存在;你需要相反,当没有更多对象时,指向对象的指针不复存在。(可以说是反向垃圾收集。)
我过去用过ManagedPtr
;指针向对象注册自身,该对象必须派生ManagingObj
自在其析构函数中将指针设置为 null 的类。这有时有效,但它仍然不会从其他对象可能保留它的列表等中删除条目。在实践中,知道您的网络资源对象的其他对象可能希望在它消失时采取特定操作。最后,您几乎总是需要使用观察者模式:任何获得指向您的对象的指针的对象都会向它注册,以便在其消亡时得到通知。
我倾向于遵循标准流使用的模式:拥有一个表示资源的对象,当它检测到(或被告知)网络不再可用时,它可以进入错误状态和/或抛出异常。如果你不能改变现有的资源类,那么这个新对象可以保存现有的资源对象(目前你所有的用户都有共享的指针),用户可以共享新的对象。
除非您需要此资源的所有用户在它变得不可用时迅速做出响应,否则尝试向所有人传播消息似乎没有任何意义。如果你只是想让他们停止使用它,他们可以在下次尝试使用它时这样做,然后发现它不再起作用了。如果他们确实需要消息,那么写一些东西来保存所有的列表,并在他们感兴趣的事件发生时调用他们的一些函数。这称为观察者模式或“侦听器”,借助这些搜索词,您可以找到实现和替代方案。
理想情况下,用户应该能够在使用资源的过程中或之后立即检查错误状态。使用前的测试通常容易出错,因为它会创建一个窗口,在该窗口中网络可能在测试之后但在使用之前变得不可用。一旦您的代码必须正确处理该案例,您不妨将其设为唯一案例,无需事先检查。