【问题标题】:Possible to create weak_ptr to set elements可以创建 weak_ptr 来设置元素
【发布时间】:2019-01-14 22:06:31
【问题描述】:

我有一个 std::multiset 对象(使用 set::emplace 就地创建)。这使我可以使用自定义比较器进行排序访问。

对象本身还包含一个指向其他对象的指针列表,这些对象标识了一些依赖项(这些依赖项不在比较器中使用,也不影响集合的底层树结构)。目前这个依赖列表被实现为一个 std::list 的原始对象指针。然而,这是不安全的,因为可以从多重集中删除依赖项,而不会通知持有这些依赖项指针的对象。

有没有办法使用weak_ptr 指向集合中的对象,而不使用集合本身中的shared_ptrs?或者是实现这一点的唯一方法是拥有一组 share_ptrs 而不是 Objects?

【问题讨论】:

  • 您能否将“已移除”的对象移动到单独的容器中(而不是删除它们)并将它们标记为“已删除”,直到您可以更新树中的指针?
  • 这很有趣;看起来我必须使用 C++17 set::extract。我看到的唯一问题是我不知道(不迭代整个树)何时不再引用单独容器中的项目。这似乎与扫描整个树并删除任何指向已删除对象的指针一样多。我认为使用 shared_ptrs 可能会更容易。
  • 好吧,我想你也可以为你的对象添加一个引用计数,当你遇到一个指向“已删除”对象的指针时,减少引用计数并删除指针。它涉及更多,但shared_ptr 会影响性能,因此这取决于您是否需要更轻松的实施或更快的操作。
  • weak_ptr 的唯一用途是将其提升为 shared_ptr(如果它有效;否则,您会得到 null 或异常),所以虽然 shared_ptr 接口可以在不支持weak_ptr 的情况下单独实现,weak_ptr 接口不能单独实现。你只能做weak_ptr<T> -> shared_ptr<T> -> T*。只要您保留shared_ptr<T>,您就只能继续使用原始指针。试图切断中间人并从弱智能指针获取原始指针不会产生可用的指针。
  • @curiousguy,我的想法更像是weak_ptr -> shared_ptr(实际上不需要获取原始指针)。我不明白的是引用计数机制只存在于shared_ptr,所以如果你没有shared_ptr作为集合中的底层元素,就没有weak_ptr给它(如解释的那样)由本·沃伊特(Ben Voigt)撰写)。

标签: c++ set weak-ptr


【解决方案1】:

std::weak_ptr 实际上指向std::shared_ptr 用来跟踪对象位置和生命周期的元数据块。如果没有shared_ptr,则没有元数据块。

可能设计一个不依赖于std::shared_ptr 的弱指针,但它不会是std::weak_ptr。弱指针和容器必须在非常深的层次上合作——你也将替换std::multiset

我相信你可能有一个更大的问题,但是......如果你从std::multiset 中删除一些东西,这可能会使指向所有元素的指针无效,而不仅仅是那些被删除的元素。在你的集合中存储std::shared_ptr 可以同时解决这两个问题。

实际上,删除部分不适用于关联容器,包括std::multiset。其他容器类型将不安全。然而,Multiset 保证

erase 成员应仅使迭代器和对已擦除元素的引用无效

【讨论】:

    【解决方案2】:

    如果你打算使用智能指针来管理一个指针,你应该使用智能指针来管理对该指针的所有访问,否则你仍然有同样的问题在等着你。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多