【问题标题】:Is there a way to keep a weak reference on an object and control its lifetime as well?有没有办法保持对对象的弱引用并控制其生命周期?
【发布时间】:2017-04-03 17:05:03
【问题描述】:
  • shared_ptr/weak_ptr 允许在对象上保留弱引用,但我不能阻止接收弱引用的人转换它并将其存储为共享。所以我失去了对对象生命周期的控制。

  • unique_ptr可以控制对象的生命周期,但是没有弱引用机制。

我找不到一种标准的方法来同时获得生命周期控制和弱引用的好处。我不敢相信我是唯一遇到这个问题的人。

标准或增强中是否有任何允许这种行为的内容? 或者是否有一种模式允许这样做而无需重写完整的 smart_ptr 类?

【问题讨论】:

  • 相关stackoverflow.com/questions/17536731/…。也有std::experimental::observer_ptr,但删除unique_ptr后不会变为null。
  • 这就是weak_ptr 的意义所在。当客户端使用引用的对象时,它会在使用期间将其转换为共享对象,这样它就不会被删除。拥有weak_ptr 的客户端在使用它之前需要某种方式来承担对象生命周期的部分所有权。
  • unique_ptr 的情况下不需要类似weak_ptr 的机制,因为存储在其中的对象的生命周期必须超过对其的所有引用的生命周期,并且引用该对象的所有代码都可以使用这些没有任何额外检查的引用。如果代码的某些部分实际上可能期望该对象不存在,那么最好通过boost::optional_reference 之类的方式授予它对对象的访问权限。

标签: c++ boost c++14


【解决方案1】:

如果你想控制生命周期,它不是弱指针。

弱指针可以升级为共享指针。因此,如果您不想共享所有权,则需要传递引用/原始指针。

您可以通过包装weak_ptr 而不暴露整个界面来制作自己的受限访问observer_ptr。但是,这在多线程设置中很难保证安全(可以说是shared_ptr 蓬勃发展的唯一设置)。

【讨论】:

    【解决方案2】:

    你要求的是不可能的。

    无法通过无法延长对象的生命周期以涵盖其访问对象的时间的代码安全地访问对象。

    要允许外部代码访问对象,您还必须允许该代码延长对象的生命周期以涵盖它访问对象的时间。

    【讨论】:

      【解决方案3】:

      好的,没有标准的方法可以做到这一点。

      解决方案是为所有对象添加 unique_ids,每个需要弱引用的人都存储一个 id。

      然后我们有一个管理器,它使用公共方法 findById(id) 保存这些对象的 unique_ptr 映射。

      这样,内存分配完全由管理器控制,任何人都可以在上面保留弱引用。

      【讨论】:

      • 这行不通。你打电话给findById(id),你得到一个可能会或可能不会随时消失的对象,因为其他东西控制了它的生命周期?!你怎么能用它?这完全等同于无法提升为强指针的弱指针,但同样无用。
      • 你是对的,findById(id) 返回我所谓的 TransientPtr,一个必须在使用前测试的指针,并且永远不能被复制或存储。所以我把这个对象用在很短的范围内,只要在我使用它的范围内不破坏它,就没有问题。我认为自定义的weak_ptr有同样的问题,如果我不能将它提升为强指针,那么在确保shared_ptr仍然存在的情况下就无法使用它。与自定义 weak_ptr 相比的优势在于,在我的情况下,对象可以在以后(从服务器)被销毁和重新创建,并且我的 id 仍然有效。
      • 那么,为什么还要麻烦这些 ID 呢?为什么不将weak_ptr 包装在一个只能将其转换为TransientPtr 的类中?包装的weak_ptr 用于ID 的用途,将其转换为TransientPtr 的功能用于findById 的用途。 ID 没有任何作用。
      • 是的,你是对的。在我的特殊情况下,ID 在服务器上是持久的,它允许我在没有资源的情况下保留一个 weak_ptr,一旦服务器告诉我创建资源,ptr 就会神奇地工作。
      猜你喜欢
      • 2015-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-21
      • 1970-01-01
      • 2012-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多