使用裸指针相比于使用weak_ptr有什么优势吗?

3

问题: 在非所有者资源上使用裸指针是否有令人信服的理由,或者我们应该使用 weak_ptr

CPP.reference 指出:

std::weak_ptr 模拟临时所有权:当对象只需要在存在时才能访问,并且它可能随时被其他人删除时

但是,Which kind of pointer do I use when? 中的被接受回答中有以下声明:

对于非所有者资源的引用以及在您知道资源将超过引用对象/作用域的情况下,请使用笨指针(裸指针)或引用。首选引用并在需要 nullability 或 resettability 时使用裸指针...如果您想要对资源进行非所有权引用,但不知道资源是否会超过引用它的对象,请将资源打包到 shared_ptr 中并使用 weak_ptr

这个答案后面有很多关于裸指针使用的来回讨论,但没有真正解决问题。我看不出使用愚笨指针的任何理由。难道我漏掉了什么?


1
共享指针和弱指针很昂贵。除非你有实际需要,否则不要使用它们。 - Kerrek SB
3
在纯粹的C++中,通常不需要使用原始指针,除非你是真正无法承受小型性能影响的0.1%之一。这完全是主观的,但大多数人都属于“始终使用智能指针”的阵营;这只是为了解释前后矛盾之处。 - Collin Dauphinee
值得考虑的第一个替代原始指针的选择通常是std::unique_ptr,而不是弱指针。只有在受管理对象的生命周期比单个函数范围或对象生命周期更复杂时,才需要使用共享和弱指针。 - Tony Delroy
未来的observer_ptr可能会解决上述大部分问题。 - vsoftco
有趣的R.30:“一个不操作生命周期的函数应该使用原始指针或引用。”但是,如果函数需要知道对象是否还存活呢?原始指针无法满足这个要求。 - rsjaffe
显示剩余6条评论
2个回答

6
一个 weak_ptr 有一个非常具体的目的: 打破 shared_ptr 的循环引用。例如,std::enable_shared_from_this 是基于让一个对象包含指向自身的 weak_ptr。如果它直接包含一个 shared_ptr,那么就会创建一个循环引用,所以它有一个 weak_ptr
在需要使用 shared_ptr 的地方使用 weak_ptrweak_ptr 有一个更高的成本,因为除了 shared_ptr 的成本之外,还有对象存在检查,这会产生一个 shared_ptr 或不产生。此外,它是一个更复杂的东西,因此更容易使用不正确。
我无法想到任何方式 weak_ptr 与“临时所有权”有任何关系(除了在检查存在并使用生成的 shared_ptr 后,那是一种暂时的共享所有权,对于每个使用都重复出现)。例如,std::enable_shared_from_this 与临时所有权无关。通常情况下,我会忽略这种说法的来源,并建议其他人忽略它,但是 cppreference.com 是我们拥有的最好的免费在线 C++ 参考资料。奇怪的是它包含一个无意义的语句。但是,没有什么是完美的,正如我曾在 clc++ 中对 Bjarne 表示的那样,在那里他纠正了我的“prefect”拼写错误。嗯!
在需要 weak_ptr 的情况下,我不知道使用原始指针比 weak_ptr 有任何优势。原始指针无法完成 weak_ptr 所需的保持 shared_ptr 控制块的工作,因此,用原始指针代替 weak_ptr 的想法似乎毫无意义。但是,当你不再因学习一些从未想过的事情而感到惊讶时,就是你死亡的那一天,因此可能存在某些我不了解的模糊用途。
此外,在需要使用原始指针的情况下,使用 weak_ptr 没有任何优势。相反,weak_ptr 引入了相对较大的成本,即控制块分配和引用计数。因此,我无法想象任何情况下用 weak_ptr 替换原始指针是有意义的,并且我不希望这是我学到的反例。

1
很抱歉告诉你,如果你想要一个非拥有的指针,除非你需要一个weak_ptr,否则你应该使用原始指针,因为它会增加额外的开销。 - Arne
1
@Arne:嗯,我同意。不需要道歉。;-) - Cheers and hth. - Alf
根据我所看到的C++会议视频,你应该使用unique_ptr来管理所有拥有指针,使用raw pointer来管理所有非拥有指针,只有在真正需要共享所有权的情况下才使用shared_ptr,例如:在两个线程之间共享对象,并且如果你明确允许对象在每次访问之间死亡,则使用weak_ptr。将shared_ptr用于所有情况被认为是不好的编码风格。 - Arne
好的,我从未使用过enable_shared_from_this,也无法想象它在哪里真正有用,因为尽管我可以从非拥有原始指针创建有效的shared_ptr,但我仍然无法询问原始指针是否仍然有效(或者我可以吗?我没有为此编写测试)。我知道weak_ptr中唯一的用途是对象缓存。 - Arne
@Arne:不,你不能询问原始指针是否有效。通常情况下,enable_shared_from_this 用于在您拥有一个已知有效的原始指针或引用(例如作为函数参数传递)并且想要存储 shared_ptr 的情况下使用。特别是在将旧代码转换为使用智能指针时,这种情况经常发生。 - Cheers and hth. - Alf
显示剩余3条评论

2

弱指针实际上用途很少。只有当你需要它的锁定功能(将指针转换为共享指针,在操作时防止垃圾回收)时,弱指针才有用。如果您只是使用原始指针,则不拥有指针最佳,因为共享和弱指针具有开销。


在操作指针所指向的对象时,什么情况下您不想防止垃圾回收? - rsjaffe
@RoryJaffe 大多数情况下,您应该设计您的应用程序,使资源的所有权和生命周期清晰明确。在这样的系统中,指针需要检查其是否仍然有效应该相对较少。 - Galik
@RoryJaffe 大多数情况下,当您将指针传递给函数时,您在调用方拥有一个指向共享指针的所有权指针,这已经防止了对象在被调用方上下文中被删除。 - Arne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接