我一直在想,虽然我理解 std::observer_ptr 的目标,但我认为如果至少有一个类似的指针类型的选项知道它所指向的内容是否被删除,那就太好了。例如,我们可以有如下所示的内容
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 expiredn"; // this will fire
使用当前标准库实现此目的的一种方法是在 A 的生命周期内存在某个范围内对 A 进行shared_ptr,始终通过传递weak_ptrs来引用 A,并在不再需要 A 时通过重置shared_ptr删除 A。此处的weak_ptrs将具有知道 A 是否已被删除的observer_ptrs的基本语义。但是这种方法存在问题:必须锁定weak_ptrs,将它们变成要使用的shared_ptrs,这感觉不整洁,但更严重的是,A 的shared_ptr必须存在于某个地方,当用户想要的只是一个不拥有任何内容的稍微聪明的指针时。用户同意在适当的时候手动销毁内容:不共享所有权,因此在这种情况下用户创建shared_ptr是一种代码异味。
但是,我想不出可以有效隐藏此实现细节的方法。
此外,这样的指针是否作为提案存在,还是在提升库中或其他地方?
这种智能指针的问题在于它比std::unique_ptr
、T*
或std::weak_ptr
更容易出错。
当您想知道指针是否已被其唯一所有者从其他地方删除时,实际上您需要共享所有权和std::weak_ptr
。
您会看到,在使用弱指针之前需要"锁定"它是有原因的。这是因为当您开始使用它时,您将获得指针的所有权。如果您无法锁定">知道是否已删除的观察者指针",则无法安全地使用它,因为在验证其有效性后的任何时刻,都可以将其删除。
还有,你还有更深层次的矛盾。
当您有一个唯一的指针时,您知道谁将删除它,并且您知道谁是所有者。
如果你有一个程序在运行时检查指针的有效性,那是因为你的程序不知道资源所有权的状态。
如果您的程序或程序的某些部分无法知道资源的所有权状态,并且需要检查它是否已被删除,那么您需要确保在使用它时不会在下一行删除它,因为它可以随时删除,因为您无法知道它的所有权状态。因此,您需要在使用资源时暂时拥有该资源。因此,您需要共享所有权才能在执行代码时推迟所有权决策。
如果您具有共享所有权,则不需要知道是否已删除的观察者指针。
那时你的指针不需要存在。
所以...你认为你需要那个指针,它可能很方便...你能做什么?
您需要查看您的代码。如果只有一个所有权,为什么需要知道指针的有效性。为什么不能简单地问主人?
如果所有者不存在,则在删除所有者时,想要执行检查的代码可能无效。也许您想要进行检查的结构应该与所有者同时死亡。
如果您的唯一所有者在不可预测的时刻死亡(例如,您的唯一所有者由共享所有者持有(,那么也许您的结构应该检查共享所有者的有效性。
也许调用函数的代码想要检查其指针是否仍然有效,当所有者死亡时,根本不应该调用它。
。
等等。
有很多方法可以解决这个问题,但是需要唯一所有者上的弱指针通常表明程序中存在缺陷或程序中对象生存期推理中存在问题。
一般不可行。
现有智能指针的全部目的是跟踪对象生存期和所有权,这通常不可能使用原始指针,除非您挂接到分配器并且此分配器与与分配对象相关的任何句柄之间存在一些复杂的关系。
您所描述的好处是使用上述现有智能指针所带来的好处。shared_ptr
和weak_ptr
在这里是完美的。
锁定没有问题(你想要这个(,也必须在某个地方有一个shared_ptr
也没有问题,因为肯定有人在某个地方拥有这些数据。如果他们不这样做,你的设计就会有更大的问题,你正试图用一个类似的破碎的智能指针概念来解决这些问题,而这个概念在标准中永远不会存在。