【问题标题】:C++ Smart Pointer performanceC++ 智能指针性能
【发布时间】:2008-11-21 11:24:55
【问题描述】:

与裸指针相比,使用智能指针,尤其是 boost::shared_ptr 在时间和内存方面的成本要高多少?对游戏/嵌入式系统的性能密集型部分使用裸指针是否更好?您会建议对性能密集型组件使用裸指针还是智能指针?

【问题讨论】:

    标签: c++ boost smart-pointers


    【解决方案1】:

    取消引用智能指针通常是微不足道的,当然对于发布模式的提升。所有 boost 检查都在编译时进行。 (智能指针理论上可以跨线程执行智能操作)。这仍然留下了许多其他操作。 Nicola 提到了建造、复制和破坏。不过,这不是完整的集合。其他重要的操作是交换、赋值和重置为 NULL。基本上,任何需要智能的操作。

    请注意,其中一些操作被一些智能指针排除在外。例如。 boost::scoped_ptr 甚至不能被复制,更不用说被分配了。由于这留下了更少的操作,因此可以针对这些更少的方法优化实现。

    事实上,随着 TR1 的出现,编译器很可能使用智能指针比原始指针做得更好。例如。编译器可能会证明智能不可复制指针在某些情况下没有别名,仅仅是因为它是不可复制的。想一想:当创建两个指向同一个对象的指针时,就会发生别名。如果第一个指针不能被复制,那么第二个指针怎么会指向同一个对象呢? (也有一些方法可以解决这个问题 - operator* 必须返回一个左值)

    【讨论】:

    • 不幸的是,您对优化智能指针的想法行不通,至少在 C++ 中是这样。在将指针放入智能指针之前,您可能已将指针存储在其他位置。此外,通过执行 &*smart_ptr; 可以轻松(但不建议)将原始 C 指针从智能指针中取出
    • 我同意克里斯·杰斐逊的观点。在将其放入智能指针之前,没有人阻止您将其存储在其他地方
    • 我在这里写了一个关于别名的小答案:stackoverflow.com/questions/270408/…
    • 您确实可以从原始指针初始化 scoped_ptr,在这种情况下编译器无法优化。我的观点是,这是个例外。编译器在优化时需要排除这些不常见的情况,就像它需要排除 &*MySmartPtr 情况一样。
    【解决方案2】:

    Boost 提供不同的智能指针。一般来说,内存占用(根据智能指针的种类而异)和性能应该不是问题。如需性能比较,您可以查看此http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/smarttests.htm

    正如您所见,性能比较只考虑了构造、复制和销毁,这意味着取消引用智能指针的成本应该与原始指针的成本相同。

    以下 sn-p 表明使用 shared_ptr<> 代替原始指针不会降低性能:

    #include <iostream>
    #include <tr1/memory>
    
    int main()
    {
    #ifdef USE_SHARED_PTR
        std::tr1::shared_ptr<volatile int> i(new int(1));
    #else
        volatile int * i = new int(1);
    #endif
    
        long long int h = 0;
    
        for(long long int j=0;j < 10000000000LL; j++)
        {
            h += *i;
        }
    
        std::cout << h << std::endl;
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      处理性能问题的唯一方法是分析您的代码。无论如何,性能问题的最大部分是想象的;只有分析才能向您指出瓶颈所在。

      如果事实证明使用智能指针会产生原始指针不会产生的瓶颈,请使用原始指针!在那之前,我不会太担心它;大多数对智能指针的操作都相当快。您可能过于频繁地比较字符串(或类似的东西),以至于它们并不重要。

      【讨论】:

        【解决方案4】:

        引用计数智能指针(最常见的类型)只会在您复制、创建和删除它们时花费更多。如果您要进行大量复制,这种额外的成本可能会很大,因为它们中的大多数都是线程安全的。

        如果您只想要一个“自动删除”指针,那么可以使用备受诟病的 auto_ptr,或者来自 C++0x 的新的、闪亮的(但还没有太多支持的)unique_ptr。

        【讨论】:

          【解决方案5】:

          当我上次使用 VC6 进行测试时,编译器无法像使用原始指针那样优化使用智能指针的代码。从那以后情况可能会发生变化。

          【讨论】:

          • 上次使用 VC6 测试旧版本的 boost(我认为是 1.34)时,编译器优化了weak_ptr 的引用计数的原子增量。这使事情运行得更快,尽管在线程库中造成了很多崩溃。
          • 我意识到 VC6 仍然被不能轻易切换的大型项目大量使用,但在这里公平地说,在 VS.NET 产品生命周期中的第二个版本 VC2003 之前,它还不是一个成熟的编译器循环。
          【解决方案6】:

          在“手动”管理的std::vector&lt;T*&gt;(即原始指针)和std::vector&lt;boost::shared_ptr&lt;T&gt; &gt; 之间有一个经常被忽视的中间点,其形式为boost::ptr_container 类。

          它们结合了原始指针容器的性能和智能指针容器的便利性(即它们提供了人们希望std::auto_ptr 的 STL 容器提供的功能,if that worked)。

          【讨论】:

            猜你喜欢
            • 2013-05-07
            • 1970-01-01
            • 2021-07-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-08-12
            • 2011-04-22
            • 1970-01-01
            相关资源
            最近更新 更多