shared_ptr or weak_ptr

本文讨论的焦点是一个对象的“可用状态”,从设计的角度看如何使用shared_ptr还是weak_ptr来考虑这个问题

这里所说的“对象可用”是指调用这个对象时是,安全的,数据是正确的,执行时能够实现对应的功能

而“对象不可用””是指调用这个对象时是,不安全的,不能保证数据的正确性,不能保证能够实现对应的功能


我们可以用“对象的生命/对象的是否存在(还活在内存中)”来表示对象的“可用状态”;当然我们可能也可以用其他方式来表示它的“可用状态”(后面有例子)

很多时候,我们可以选择用“对象的生命/对象的是否存在”来表示对象的“可用状态”, 因为这样的做法很多时候简单合理(尤其是函数指针时);

而且,“对象的生命/对象的是否存在”也是“对象可用状态”的必要非充分条件,

因为当对象不存在时,它也肯定就不可用了;这里“不可用”是指不能调用这个对象的属性或方法

而当对象仍存在时,依据设计,可能它早已不可用;这里“不可用”是指,如果仍去调用这个对象的属性或方法,不能完成原有功能,不能保证安全


如果我们选择用“对象的生命/对象的是否存在”来表示对象的“可用状态”

那么“对象的生命/对象的是否存在”就等价于它的“可用状态”,这时我们就应该慎用shared_ptr


当多个client使用shared_ptr来共享了一个对象时,“对象的生命/对象的是否存在”就被这些client平等地共享了

比如clientA, clientB使用一个相同的shared_ptr<Object> p

当clientA释放了p,而clientB没有释放p,p所指的对象不会被释放,这个对象还活着还存在 --> 那么就说明了这个对象还“可用”

也就是说,clientA和clientB共同决定了p所指的对象的可用状态,当任一个client不删它它就仍然可用


但是有时,从需求来说,并不是想让clientA和clientB共同来决定p所指的对象是否可用

有时只想让clientA来决定p所指的对象的可用状态,

而只有当p所指的对象仍然可用(仍然活着)时clientB才去使用这个对象,不希望clientB来决定p所指对象的可用状态

这时clientB就不应该使用shared_ptr,clientB用weak_ptr更合适

因为clientB需要的是一个“观察者”,clientB不应该享有“决定这个对象生命/可用状态的权利”


任何涉及“可用状态”的对象,当选择用“对象的生命/对象的是否存在”来表示对象的“可用状态”时,都应该仔细考虑这个问题

这里的p可以是函数对象,也可以是指向clientA,等等


如果涉及了多个对象,比如clientB使用functorA的一个函数对象,函数的参数又指向其他几个对象paramC,paramD,函数内部又使用其他函数对象functorE

那么每个使用对象的地方都应该考虑对象可用状态的问题

所以,clientB应该想到functorA和paramC,paramD的可用状态;functorA应该考虑到paramC,paramD和functorE的可用状态


===========================================================================================================


当然我们可能也可以用其他方式来表示它的“可用状态”,下面只是一种小例子

比如clientA可以调用clientB.subscribe(XXX, p)来把p传给clientB,XXX表示一个想订阅的东东

当clientA不再需要订阅时,再调用clientB.unsubscribe(XXX)

这时可以设计让clientB 默认unsubscribe后,p就不再可用了



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值