【问题标题】:Why doesn't std::shared_ptr dereference throw a null pointer exception (or similar)?为什么 std::shared_ptr 取消引用不抛出空指针异常(或类似异常)?
【发布时间】:2015-12-22 05:53:40
【问题描述】:

异常是 C++ 的重要组成部分,使用它的原因之一(我知道有很多,更重要的,其他原因)是避免不必要的检查,用大量 if 语句混淆代码(也许这是不正确的假设吗?)。

所以现在我很好奇为什么 std::shared_ptr::operator*std::shared_ptr::operator-> 不抛出 null_ptr_exception 或类似的?

【问题讨论】:

  • 您是否找到了执行所描述行为的智能指针的实现?
  • @aggsol,不,我们最终使用现有的实现和模板策略自己制作

标签: c++ exception


【解决方案1】:

我的理解是智能指针类被设计成看起来和行为像原始指针。鉴于这一指导性设计原则,理想情况下,遗留代码可以使用等效的所有权语义简单地将原始指针的使用替换为智能指针,并且代码将完全像以前一样工作。

因此,更改解除引用智能指针的行为不应进行任何额外的检查或引发异常(即,因为原始指针不这样做)。

向标准添加智能指针的提议表明了这一设计决策 (A Proposal to Add General Purpose Smart Pointers to the Library Technical Report):

三。设计决策

A.一般原则

  1. “尽可能接近原始指针,但没有更接近”

【讨论】:

  • 感谢您的回答。我必须承认标准委员会的理由并不令人满意。如果我们确实用智能指针替换了遗留代码,那么null_ptr_exception 将被取消处理并且程序无论如何都会中断(就像一个断言,虽然在没有展开的情况下被授予 - 然后再次,就像一个断言,这个异常可以被分解为由调试器)。
  • @Samaursa 对于取消引用空指针的原始指针会触发未定义行为,并且程序可能看起来运行正常,但我理解您的观点和沮丧。
  • 我不喜欢这个设计。也许我们应该有另一个更现代的智能指针。
【解决方案2】:

如果共享指针的每次取消引用都需要检查 nullptr 并有条件地抛出异常,则可能会有大量冗余检查、代码膨胀和开销。当然 - 优化器可能会消除其中的一些,但仍然......相反,程序员希望在多次取消引用之前检查一次。

【讨论】:

  • 但这不是支持/反对异常/错误代码的论据吗?
  • @Samaursa: 不...取消引用原始指针或标准库智能指针允许生成假定指针永远不会为 nullptr 的机器代码 - 该机器代码将比必须执行的代码运行得更快检查并避免(对于相同的非 nullptr 情况)分支到错误处理代码。不检查/分支会更快,无论是否使用异常或错误代码(它们本身可能在速度和机器代码大小上有所不同)进行处理。
  • 我希望unique_ptr 有一个断言和shared_ptr(因为它已经是一个具有引用计数和跟踪weak_ptrs 的重对象)到throw。尽管如此,它还是有意义的,因为指针取消引用是一种极其常见的操作。
  • @Samaursa:任何人都可以轻松地包装一个指针以在他们自己的代码中添加检查,但如果它被烘烤,你将永远无法恢复速度。还希望人们可以从原始指针使用迁移到unique_ptr,知道没有降低性能的风险(好吧,他们可能应该检查一次他们的实现,但在那之后)......节省了很多性能分析这样的变化。假设unique_ptr 做了assert... 任何希望他们的程序不被停止的人都必须自己检查nullptr 并抛出,所以有双重检查。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-09
  • 2015-09-19
  • 2020-11-22
  • 2020-08-10
  • 2013-03-21
相关资源
最近更新 更多