【问题标题】:Are there any reasons not to use Boost::shared_ptrs?有什么理由不使用 Boost::shared_ptrs?
【发布时间】:2009-02-26 05:21:14
【问题描述】:

我问了几个关于内存管理的问题(herehere),总是有人建议我使用 boost::shared_ptrs。

鉴于它们看起来很有用,我正在认真考虑切换我的整个应用程序以使用 boost::shared_ptrs。

但是,在我双脚跳入并执行此操作之前,我想问一下——有没有人对 boost::shared_ptrs 有任何不好的经历?使用它们是否有一些我需要注意的陷阱?

现在,它们看起来好得令人难以置信 - 自动处理了我的大部分垃圾收集问题。有什么缺点?

【问题讨论】:

    标签: c++ memory-management


    【解决方案1】:

    缺点是它们不是免费的。当scoped_ptr/scoped_array(或普通的旧堆栈分配)可以使用时,您尤其不应该使用shared_ptr/shared_array。如果有的话,您需要使用weak_ptr 手动中断循环。您链接到的向量问题是我可能会找到shared_ptr 的一种情况,第二个问题我不会。不复制是一种过早的优化,特别是如果字符串类已经为你做了。如果字符串类被引用计数,它也将能够正确地实现 COW,而 shared_ptr<string> 方法实际上无法做到这一点。使用shared_ptrwilly-nilly 还会引入与外部库/api 的“界面摩擦”。

    【讨论】:

    • 字符串通常不使用 COW。它不能很好地与多线程应用程序一起使用,因此大多数实现再次放弃了它。这意味着字符串副本有些昂贵。
    • GCC 的字符串实现仍然使用 COW IIRC。但是对于 C++0x,它们将可能被禁止 (open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2668.htm) - 并且很好摆脱。
    【解决方案2】:

    在 C++ 中提升共享指针或任何其他内存管理技术都不是灵丹妙药。仔细编码是无可替代的。如果您深入使用 boost::shared_ptr,请注意对象所有权并避免循环引用。您将需要显式中断循环或在必要时使用 boost::weak_ptr。

    还要小心,从分配实例的那一刻起,始终对实例使用 boost::shared_ptr。这样你就可以确定你不会有悬空的引用。确保这一点的一种方法是使用工厂方法,在 shared_ptr 中返回新创建的对象。

    typedef boost::shared_ptr<Widget> WidgetPtr;
    WidgetPtr myWidget = Widget::Create();
    

    【讨论】:

      【解决方案3】:

      我经常使用 shared_ptr。

      由于 Shared_ptr 是按值复制的,您可能会产生复制指针值和引用计数的成本,但如果使用 boost::intrusive_ptr,则必须将引用计数添加到您的类中,并且没有比使用原始指针的额外开销。

      但是,根据我的经验,在超过 99% 的情况下,在整个代码中复制 boost::shared_ptr 实例的开销是微不足道的。通常,正如 C. A. R. Hoare 所指出的,过早的优化是没有意义的——大多数情况下,其他代码将使用比复制小对象的时间更多的时间。你的旅费可能会改变。如果分析显示复制是一个问题,您可以切换到侵入式指针。

      如上所述,必须使用weak_ptr 打破循环,否则会出现内存泄漏。这将发生在诸如某些图之类的数据结构中,但是,例如,如果您正在创建一个叶子从不向后指向的树结构,您可以只使用 shared_pointers 来表示树的节点,而不会出现任何问题。

      正确使用 shared_ptr 可以大大简化代码,使其更易于阅读和维护。在许多情况下,使用它们是正确的选择。

      当然,如前所述,在某些情况下,使用 scoped_ptr(或 scoped_array)是正确的选择。如果指针未被共享,请不要使用共享指针!

      最后,最新的 C++ 标准提供了 std::tr1::shared_ptr 模板,该模板现在在大多数平台上,虽然我不认为 tr1 存在侵入式指针类型(或者更确切地说,可能存在,但我自己没听说过)。

      【讨论】:

        【解决方案4】:

        动态内存开销(即额外分配)加上与引用计数智能指针相关的所有开销。

        【讨论】:

          猜你喜欢
          • 2010-09-29
          • 2013-09-27
          • 2011-11-16
          • 1970-01-01
          • 1970-01-01
          • 2020-04-08
          • 1970-01-01
          • 2010-10-11
          • 2010-10-10
          相关资源
          最近更新 更多