是否可以在标准弱指针之上实现非拥有 "slightly smart" 指针?

Is it possible to implement a non-owning "slightly smart" pointer on top of standard weak pointers?

我一直在想,虽然我理解 ,但我认为如果至少有一个类似指针类型的选项,知道它指向的内容是否已被删除,那会很好。例如,我们可以有类似下面的内容

slightly_smart_ptr<Foo> p1(new Foo());
auto p2 = p1;
p1.erase(); // This deletes the foo referred to by p1.
if (p2.expired())
   std::cout << "p2 is expired\n"; // this will fire

使用当前标准库实现此目的的一种方法是 make a shared_ptr to A in some scope that will exist for the lifetime of A, always refer to A by passing weak_ptrs around,并在不再需要时通过重置 shared_ptr 删除 A。这里的 weak_ptrs 将具有 observer_ptrs 的基本语义,即知道 A 是否已被删除。但是这种做法有问题:weak_ptrs必须加锁,变成shared_ptr才能用,感觉不整洁,但更严重的是一个shared_ptr到A必须存在某处,当用户想要的只是一个不拥有任何内容的稍微智能的指针。用户同意在适当的时候手动销毁内容:没有共享所有权,因此用户在这种情况下创建 shared_ptr 是一种代码味道。

但是我想不出可以有效隐藏此实现细节的方法。

还有这样的指针作为提案或在 boost 库或其他地方存在吗?

一般来说不可行。

现存智能指针的全部目的是跟踪对象的生命周期和所有权,这种方式通常使用原始指针是不可能的,除非你连接到分配器并且在这两者之间有一些复杂的关系分配器和任何属于已分配对象的句柄。

您所描述的好处是使用所述现存智能指针所带来的好处。 shared_ptrweak_ptr 在这里很完美。

锁定没有问题(你想要这个)并且在某处必须有一个 shared_ptr 也没有问题,因为肯定 某人 某处确实拥有该数据.如果他们不这样做,那么您的设计就会遇到更大的问题,并且您正试图使用​​标准中永远不会存在的类似损坏的智能指针概念来解决这些问题。

这种智能指针的问题是它比std::unique_ptrT*std::weak_ptr更容易出错。

当您想知道指针是否已被其唯一所有者从其他地方删除时,实际上您需要共享所有权和 std::weak_ptr

你看,在使用弱指针之前需要“锁定”它是有原因的。这是因为当你开始使用它时,你就获得了指针的所有权。如果你不能锁定你的“知道是否删除的观察者指针”,你就不能安全地使用它,因为在验证它的有效性后随时可以删除它。


另外,你还有更深层次的矛盾

当你有一个独特的指针时,你知道谁会删除它,你也知道谁是所有者。

如果您有一个程序在运行时检查指针的有效性,那是因为您的程序不知道资源所有权的状态。

如果您的程序或程序的一部分无法知道资源的所有权状态并且需要检查它是否已被删除,那么您需要确保它不会被删除下一行在使用它时,因为它可以随时删除,因为您无法知道它的所有权状态。因此,您需要在使用资源时暂时拥有该资源。因此,您需要共享所有权以在执行代码时推迟所有权决定。

如果您拥有共享所有权,则不需要知道是否删除的观察者指针

那时你的指针不需要存在。


所以...您认为您需要那个指针,它可能很方便...您能做什么?

您需要检查您的代码。如果只有一个所有权,为什么你需要知道指针的有效性。为什么不能直接问店主?

如果所有者不存在,则当所有者被删除时,您想要进行检查的代码可能无效。也许您想要进行检查的结构应该与所有者同时死亡。

如果您的唯一所有者在不可预知的时刻死亡(例如,您的唯一所有者由共享所有者持有),那么也许您的结构应该检查共享所有者的有效性。

也许你调用函数的代码想要检查它的指针是否仍然有效,当所有者已经死了时,你应该简单地不调用它。

...

以此类推

有很多方法可以解决这个问题,但需要一个唯一所有者的弱指针通常表明程序存在缺陷或程序中对象生命周期的推理存在问题。