【问题标题】:C++11: Replace all non-owning raw pointers with std::shared_ptr()?C++11:用 std::shared_ptr() 替换所有非拥有的原始指针?
【发布时间】:2012-01-10 10:25:15
【问题描述】:

随着std::unique_ptr的出现,伤痕累累的std::auto_ptr终于可以安息了。所以在过去的几天里,我一直在更改我的代码以使用智能指针并从我的代码中删除所有delete

虽然 valgrind 说我的代码是内存干净的,但智能指针的语义丰富性将使代码更清晰、更易于理解。

在大部分代码中,翻译很简单:使用std::unique_ptr 代替拥有对象持有的原始指针,扔掉delete,并小心撒上get()reset() 和@987654329 @ 调用,根据需要,与其余代码很好地交互。

我现在正在将非拥有原始指针转换为智能指针。

由于我对对象的生命周期非常小心(我确保我的模块仅依赖于一个方向),因此 valgrind 告诉我没有任何未初始化的读取、悬空指针或泄漏。所以,从技术上讲,我现在可以不理会那些非拥有的原始指针

但是,一种选择是将那些 非拥有原始指针 更改为 std::shared_ptr,因为我知道它们是非循环的。或者,将它们保留为原始指针会更好吗?

我需要一些资深智能指针用户的建议,关于您使用什么经验法则来决定是保持 非拥有原始指针 原样,还是将它们转换为std::shared_ptr 请记住,我经常对代码进行单元测试和验证。

编辑:我可能误解了std::shared_ptr 的使用——它们可以与std::unique_ptr 一起使用,还是如果我使用std::shared_ptr,所有句柄也应该是std::shared_ptr

【问题讨论】:

  • 共享指针拥有
  • 所以所有共享指针本质上都“平等地拥有”该对象,对吧?所以我应该将它保留为一个唯一的 ptr + 许多原始指针或只是许多共享指针,这取决于我的语义意图?对吗?
  • @kfmfe04:当您需要多个事物拥有一个资源时使用shared_ptr(并且拥有事物的人可能会“随机”进出范围),当您需要一个资源时使用unique_ptr thing 拥有该资源,并在您只需要引用它而不拥有它时使用原始指针(并期望此引用不会持续超过资源存在的时间)。
  • 你可以使用一个共享ptr和许多弱ptr。
  • 有一个关于非拥有的“哑”智能指针的提议,称为“observer_ptr”,它没有真正的目的,只是为了澄清指针的非拥有角色:open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3840.pdf

标签: c++ memory c++11 smart-pointers


【解决方案1】:

就我个人而言,这就是我(或多或少)这样做的方式:

  • unique_ptrs 仅供个人拥有
  • 原始指针意味着给我原始指针的人保证该对象的生命周期匹配或超过我的生命周期。
  • shared_ptrs 用于共享所有权
  • weak_ptrs 用于当系统想要在使用之前检查对象是否仍然存在时。这在我的代码中很少见,因为我发现让系统保证它通过它的子系统的任何东西的生命周期更简洁(在这种情况下我使用原始指针)

到目前为止,我使用的 unique_ptrs 比 shared_ptrs 多,原始指针多于弱指针。

【讨论】:

  • +1 不要让简单的事情变得困难。不要把简单的事情复杂化。
  • +1 您的观察与我在该领域的有限经验一致 - 很高兴得到肯定和明确的使用说明 - ty
  • 在极少数情况下,您会在 reference 上使用 原始指针。还是在使用前认真检查指针是否为nullptr
  • @LCIDFire 不,我几乎从不传递可以选择为空的原始指针;这不是通过原始指针传递的理由。当对象仅在方法范围内使用时,我通过引用传递。当方法存储超出其调用范围的指针(通常作为类成员)时,我通过指针传递。显然,您可以只获取传递给您的引用地址,但我相信按照我上面所说的做会更清楚。
  • 另外,您始终可以通过将 shared_ptr 强制转换为布尔值来检查它是否有效。
【解决方案2】:

当您需要多个事物拥有一个资源时使用shared_ptr(并且拥有事物的人可能会“随机”进入和超出范围),当一个事物拥有该资源时使用unique_ptr,并使用原始指针,当您只需要引用它而不拥有它时(并期望此引用不会持续超过资源存在的时间)。

还有第四种类型,一种用于shared_ptr 的原始指针,称为weak_ptr。你用它来指代shared_ptr,但实际上并不拥有它;然后您可以检查对象是否仍然存在并使用它。

【讨论】:

    【解决方案3】:

    标准库中唯一的非拥有智能指针是std::weak_ptr。但是,要使用它,实际拥有的对象需要将指针保存在 std::shared_ptr 中。

    我假设您之前使用过std::unique_ptr。如果您现在将它们转换为shared_ptr,您将受益于您的非拥有指针可以知道丢失的拥有指针是引用,而原始指针可以悬空而没有任何机会让非拥有组件检测到这一点.但是,shared_ptr 会比unique_ptr 产生(非常?)小的性能和内存开销。

    就个人而言,我建议在一般情况下使用一个shared_ptr 和多个weak_ptrs 而不是一个unique_ptr 和许多原始指针,如果您确实遇到性能问题,请使用unique_ptr

    【讨论】:

    • +1 使用weak_ptr 来保存指针引用,即使只有一个所有者。 weak_ptr 的好处在于它实际上检查 以查看对象是否已消失。它使您能够进行一些验证以查看对象是否被删除。裸指针无法做到这一点。
    猜你喜欢
    • 2012-09-07
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 1970-01-01
    • 2013-08-18
    相关资源
    最近更新 更多