【问题标题】:A shared pointer which is conceptually owned by one, unique, object概念上由一个唯一对象拥有的共享指针
【发布时间】:2021-10-04 14:36:44
【问题描述】:

当有一个明确的理由认为“一个唯一的对象拥有指针”时,在 C++ 中处理共享指针的规范方法是什么?

例如,如果shared_ptr 是特定类的成员,该类负责初始化指针,那么可以说该类也应该对何时删除指针有最终决定权。

换句话说,可能是当所属类超出范围时(或者本身是delete'd,对指针的任何剩余引用都不再有意义。这可能是由于相关变量是被破坏类的成员。

这是一个示例的草图

class Owner
{

    Owner()
    {
        p.reset(malloc_object(arguments), free_object);
    }

    std::shared_ptr<type> get() { return p; } 
        // seems strange because now something somewhere
        // else in the code can hold up the deletion of p

    // unless a manual destructor is written
    ~Owner()
    {
        p.reset(nullptr); // arduous
    }

    std::shared_ptr<type> p;
    int a, b, c; // some member variables which are logically attached to p
                 // such that neither a, b, c or p make sense without each other
}

不能使用unique_ptr,因为这不允许get 函数返回指针,除非返回原始指针。 (这是可以接受的解决方案吗?)

unique_ptr 结合从 get 函数返回的 weak_ptr 可能有意义。但这不是有效的 C++。 weak_ptrshared_ptr 结合使用。

带有返回 weak_ptr 的 get 函数的 shared_ptr 比原始指针更好,因为要使用弱指针,必须将其转换为共享指针。如果引用计数已经为零并且对象已被删除,这将失败。

但是使用shared_ptr 会破坏这一点,因为理想情况下会选择unique_ptr,因为只有一个东西“拥有”指向的数据。

我希望这个问题足够清楚,因为我无法复制我正在使用的代码,所以很难解释。

【问题讨论】:

  • 在我看来,显而易见的问题是为什么要传递指向对象内部状态的指针。由于您概述的原因,通常不鼓励这样做。
  • 如果Owner 拥有p 指向的type 对象,那么p 一开始就不应该是shared_ptr。但如果你真的需要,那么shared_ptr 的别名构造函数可能在这里有用,如果你将Owner 对象存储在shared_ptr 中,然后让p 指向type 但依赖@987654343而是 @ 的共享所有权。
  • 这不正是weak_ptr存在的原因吗?您能否在您的用例中澄清weak_ptr 的缺点。
  • shared_ptr 的问题在于它实际上是一个全局的——联合所有所有者。使用 unique_ptr 并分发非拥有的原始指针存在原始指针变成悬空指针的问题。这是一种权衡,两种方法都有优点/缺点,并且需要一定程度的纪律。 (无论哪种方式,暴露的对象都可以被改变,除非只暴露了 const 对象。)
  • 我能想到在这里使用shared_ptr 的唯一原因是,如果你想绕过weak_ptrs,这样你就有了防止悬空的措施。

标签: c++ pointers shared-ptr unique-ptr ownership


【解决方案1】:

在那里返回shared_ptr 是可以的,会发生的情况是指针仍将保留在Owner 类之外的某个地方。由于您在析构函数处执行p.reset(nullptr);,因此持有shared_ptr 的人现在将持有指向null 的指针。

weak_ptrshared_ptr 一起使用也是一个很好的解决方案,问题是相同的,即代表p 的最佳类是unique_ptr,正如您所描述的。

我会选择的路径是持有一个看起来更合适的unique_ptr,并像这样实现get()函数:

type* get() { return p.get(); }

行为相同,代码更清晰,因为将p 设置为unique_ptr 将清楚说明应该如何使用它。

【讨论】:

  • 好的,谢谢,我想我误解了...所以如果任何“共享指针”调用函数reset() 使引用同一资源的所有其他共享指针无效?
  • @FreelanceConsultant 绝对不是这样。 shared_ptr 的意义在于拥有原始shared_ptr 副本的所有其他人仍将引用原始对象。他们确实没有看到空指针。
  • 在那种情况下,这似乎与我的预期相反。我认为调用 reset 至少会将引用计数减少 1?
猜你喜欢
  • 2022-11-15
  • 1970-01-01
  • 2018-06-03
  • 2014-08-24
  • 1970-01-01
  • 2014-03-05
  • 1970-01-01
  • 1970-01-01
  • 2018-11-12
相关资源
最近更新 更多