【问题标题】:boost, shared ptr Vs weak ptr? Which to use when?提升,shared_ptr 与 weak_ptr?什么时候用?
【发布时间】:2011-01-03 10:02:16
【问题描述】:

在我当前的项目中,我非常广泛地使用boost::shared_ptr

最近我的队友也开始使用weak_ptr。我不知道该使用哪一个以及何时使用。

除此之外,如果我想将weak_ptr 转换为shared_ptr,我该怎么办。锁定weak_ptr 以创建shared_ptr 会影响我在其他线程中的代码吗?

【问题讨论】:

    标签: c++ memory-management boost shared-ptr weak-ptr


    【解决方案1】:

    总的来说和总结,

    强指针保证它们自己的有效性。例如,在以下情况下使用它们:

    • 您拥有被指向的对象;你创建它并销毁它
    • 如果对象不存在,您没有定义行为
    • 您需要强制该对象存在。

    弱指针保证知道它们自己的有效性。例如,在以下情况下使用它们:

    • 您可以访问它,但它不是您的。
    • 如果对象不存在,您已经定义了行为

    弱指针上的Lock()返回一个强指针;这就是您访问弱指针的方式。如果对象不再有效(它已被删除等),那么强指针将为 NULL,否则,它将指向该对象。你需要检查一下。

    它是这样设置的,因此您在使用它时不会意外删除该对象,因为您已经创建了一个临时(本地)强指针,因此在该强指针保留时保证了该对象的存在。当您使用完对象后,通常会让强指针超出范围(或重新分配它),然后允许删除该对象。对于多线程,请像对待其他没有内置线程安全的东西一样小心对待它们,注意我上面提到的保证在多线程时成立。 AFAIK 过去他们没有做任何特别的事情。

    boost 共享指针还具有类似垃圾收集器的功能,因为当指向对象的最后一个强指针消失或指向其他地方时,该对象将被删除。

    还有其他答案中提到的性能和循环依赖。

    从根本上说,boost 共享指针库可以让您不会弄乱组合程序,但它不能替代花时间正确设计指针、对象所有权和生命周期。如果您有这样的设计,您可以使用该库来强制执行它。如果您没有这样的设计,您可能会遇到与以前不同的问题。

    【讨论】:

    • 我喜欢它不断出现......在采访中:D
    【解决方案2】:

    当您创建的对象包含循环引用时使用weak_ptr,即shared_ptr 指向一个对象,而shared_ptr 又指向您自己。这是因为shared_ptr 无法处理循环引用 - 当两个对象超出范围时,相互引用意味着它们不是“垃圾收集”,因此内存丢失并且您有内存泄漏。由于weak_ptr不会增加引用计数,所以不会出现循环引用问题。这也意味着一般来说,如果您只想获取一个指向引用计数的指针并且不想增加其引用计数,那么请使用weak_ptr

    否则,您可以使用shared_ptr

    如需更多信息,请查看 Boost documentation

    【讨论】:

    • 这是错误的,甚至是荒谬的。当您需要所有权时,请使用拥有(强)智能指针。如果您希望能够在对象仍然存在的情况下获得强指针,并且如果它已被破坏则什么都没有,请使用弱指针。 Narfanator完美地解释了这一切。如果你有循环,你也不能使用。
    • @curiousguy boost.org/doc/libs/1_47_0/libs/smart_ptr/shared_ptr.htm '使用weak_ptr 来“打破循环。”' 所以是的,当你有循环时,你可以使用弱指针。此外,OP 询问了 shared_ptr 和 weak_ptr,因此有理由认为忽略提及 scoped_ptr 是可以的。否则,我只是说您可以使用 shared_ptr,并不是说您必须使用它或它是您唯一的选择,我也没有提供有关它的不准确信息(我什至没有提供任何信息),我什至链接了文档。这有什么“错误”或“荒谬”?
    • @curiousguy 我并不反对你说 Narfanator 的解释是正确的 - 我只是在他之前回答了。
    • @curiousguy 那只是语义。将循环定义为不存在,即仍然存在一个指针循环,但循环的一个边缘是一个weak_ptr引用,正在打破循环!所以你承认当有一个循环时可以使用weak_ptr,只是用你的话循环不复存在,这正是我所说的措辞不同。
    • 那么谁赢得了这场辩论?
    【解决方案3】:

    共享指针实现引用计数,弱指针不影响引用计数,如果你没有指向对象的共享指针,只有弱指针,对象被删除,弱指针现在告诉你对象已经丢失.

    使用弱指针有两个原因:

    1. 消除引用计数增加/减少的成本;但是您不应该这样做,因为它容易出错并且不会真正节省太多时间
    2. 在簿记数据结构中,例如您拥有所有“活动”对象 Foo 的索引,即在其他地方使用,并且如果所有“真实”使用都已结束,您不希望 Foo 在索引中保持活动状态。这是弱指针的基本实际用例。当然也有其他的。

    因此,一般而言,我的建议是仅在您知道要删除引用的对象并希望检测到它时才使用弱指针。在其他情况下,使用共享指针(引用计数)或直接指针,尤其是。当您知道对象不会被删除时,在方法局部变量中。虽然也容易出错,但比共享指针更快。

    注意循环对象不需要弱指针,您可以在大多数正确构造的程序中使用非熟化的常规指针。不过,弱指针的风险较小。

    【讨论】:

    • @Trent 实际上没有,这是一个错字——它是前两个,然后我将其编辑为“三个”以适应另一个答案关于周期性结构的评论,但我开始想知道为什么,因为这不是垃圾收集语言中的弱指针,然后我意识到你不需要它们,所以我删除了它并添加了 NB当然你可以使用它们,但它们基本上只是一种断言,循环对象不需要它们
    • 弱指针确实会影响引用计数 - shared_ptr 实现需要保持单独的强引用计数和弱引用计数,原因太复杂而无法评论。 weak_ptr 是打破循环,故事结束。
    • 越来越宗教化了。但是弱指针也存在于适当的垃圾收集语言中。弱指针的概念最初与循环无关,而是检测到后面的对象已被资源管理器删除(如引用计数、垃圾回收等)
    • 我不想信奉宗教,但我认为使用原始指针指向智能指针中保存的内存并不安全,请参阅我的 answer 来回答不同的问题。
    • "使用弱指针有两个原因" 这是错误的。 您要么需要强引用,要么不需要。 您无法在弱引用或强引用之间进行选择,这是由设计约束强加的。
    【解决方案4】:

    除非您尝试实现垃圾收集器,否则您可能根本不应该尝试使用弱指针,这在 C++ 中并不是一个热门的想法,因为要足够密切地跟踪所有可能出错的东西太难了。

    【讨论】:

      猜你喜欢
      • 2013-07-06
      • 2021-06-20
      • 2013-03-22
      • 2016-03-06
      • 1970-01-01
      • 1970-01-01
      • 2017-03-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多