【问题标题】:shared_ptr vs scoped_ptrshared_ptr 与 scoped_ptr
【发布时间】:2010-12-18 17:50:51
【问题描述】:

scoped_ptr 不可复制,正在从范围中删除。所以它有点受限制shared_ptr。因此,除了确实需要限制复制操作的情况外,shared_ptr 似乎更好用。因为有时您不知道是否需要创建对象的副本。所以问题是:除了上面提到的情况,我们是否认为shared_ptrscoped_ptr 更好(或推荐)使用。 scoped_ptrshared_ptr 工作得更快,还是有什么优势?

谢谢!

【问题讨论】:

    标签: c++ boost shared-ptr smart-pointers scoped-ptr


    【解决方案1】:

    shared_ptrscoped_ptr 更重量级。它需要分配和释放一个引用计数对象以及托管对象,并处理线程安全的引用计数——在我工作的一个平台上,这是一个很大的开销。

    我的建议(一般而言)是使用满足您需求的最简单的对象。如果您需要引用计数共享,请使用shared_ptr;如果您只需要在完成单个引用后自动删除,请使用scoped_ptr

    【讨论】:

    • 迈克,我完全同意。我总是建议人们从boost::scoped_ptr 开始。如果您需要所有权语义的转移(保持单一所有权),则“升级”到std::auto_ptr。如果您只需要共享所有权,那么您使用boost::shared_ptr。此外,Boost.ptr_container 库是 boost::shared_ptr 容器的一个很好的替代方案,当元素不需要共享时。
    • 顺便说一句:如果您确实需要共享指针,您可以通过使用make_sharedallocate_shared 而不是new 分配对象来摆脱额外的分配。
    • @David:我基本同意,但我会完全跳过auto_ptr。它不能在标准容器中安全使用,因此如果您不真的小心,它可能会带来一些令人讨厌的惊喜。
    • 同意,尤其是从 c++11 开始不推荐使用 auto_ptr,因此不建议使用它,而是我会提到 unique_ptr。
    【解决方案2】:

    性能 - shared_ptr 具有更多功能,但也需要额外分配(它也更大,但这并不重要)。

    [edit] 使用make_shared 可以避免第二次分配,但随后weak_ptr 将保留整个分配,即使在对象被销毁后,这对于大对象来说可能是个问题。

    意图表达使用scoped_ptr 更明确地说明你想做什么。 (如果您想知道 - 这是一件好事:))。如果您正确执行此操作,shared_ptr 还将指示“此对象旨在超出此范围”

    【讨论】:

    • +1 表示意图。在这种情况下,scoped_ptrshared_ptr 一样非常清楚。同样,使用std::auto_ptr 应该表明您愿意在某个时候转让对象的所有权。
    【解决方案3】:

    它们的预期目的不同,因此,在许多情况下,“shared_ptr 与 scoped_ptr”根本不是问题。当然,当您只需要一个 scoped_ptr 时,您可以使用 shared_ptr。但有什么意义呢? shared_ptr 涉及所有引用计数的开销可能稍大。

    【讨论】:

      【解决方案4】:

      scoped_ptrshared_ptr 运行得更快。这是正确的。 shared_ptr 始终使用您的分配器或默认分配器分配内存。

      【讨论】:

        【解决方案5】:

        Scoped_ptr 与 shared_ptr、weak_ptr 或 unique_ptr 几乎没有共同之处,因为它只是在做非常特殊的“引用计数”。在精心设计的代码中,这不是您经常需要的东西,但它是一个很好的工具。

        基本上,scoped_ptr 根本不是引用计数的东西。相反,它是您在堆栈上(在本地范围内)创建的对象,因此您可以执行以下操作:

          //Some enclosing scope- anything set off by "{}" or even a function:
           {
               scoped_ptr<MyObject> ptr = new MyObject( parameters...);
           } // When we hit this closing brace, "ptr" will delete the "MyObject" inside.
        

        您更倾向于在互斥锁和其他同步原语中看到这种模式 - 我可以声明一个“AutoLock”,它将锁定传递给它的互斥锁,然后在它删除时解锁它以将整个“{}”范围变成一个临界区。

        还要注意,“scoped_ptr”只有在您由于某种原因不能像“MyObject obj(params..)”这样简单的旧堆栈分配时才有意义。毕竟,它所做的是让您使用堆分配的对象,就好像它是堆栈上的对象一样。与 shared_ptr 及其表亲的引用计数相比,这往往是一个更罕见的用例。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-09-27
          • 2012-03-03
          • 1970-01-01
          • 2014-03-25
          • 2013-01-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多