【问题标题】:Raw Pointer Management in C++C++ 中的原始指针管理
【发布时间】:2010-11-23 10:17:30
【问题描述】:

我有一段性能关键代码。类和对象相当大,因此,它将作为指针存储在 STL 容器中。当指向对象的指针需要基于某些逻辑存储在多个不同的容器中时,就会出现问题。处理对象的所有权非常混乱,因为我无法将对象的所有权隔离到单个容器(我可以从单个容器中删除)。除了使用智能指针(因为它对性能至关重要,智能指针可能会影响性能),我还能做什么?

谢谢。

【问题讨论】:

  • 试试智能指针。配置文件以检查它是否确实有太大的影响。很有可能,它不会太多,而且可能比大多数自己动手的解决方案要少。
  • 不幸的是,您无能为力。您需要定义责任,即谁负责拥有您的资源。在我看来,这是 C++ 的一个基本问题,并且可能是人们转向其他语言的最大原因之一。
  • 您是分析智能指针还是只是您的猜测?

标签: c++ linux


【解决方案1】:

您要求不可能 - 从某一点来看,您要求卓越的性能,例如您声称无法提供的智能指针,并且您还碰巧要求安全和整洁。好吧,实际上,一个是以另一个为代价的。当然,您可以尝试编写自己的共享指针,这将比 boost 更轻量级,但仍提供基本功能。顺便说一句,您真的尝试过 boost::shared_ptr 吗?它实际上会降低性能吗?

【讨论】:

  • 关于shared_ptr的一点:最好使用make_shared来构建,效率更高。
  • 另外,您可以禁用 shared_ptr 的线程安全以避免支付互斥体的成本。
【解决方案2】:

你的问题很尴尬:你要求表现的逻辑很乱?

shared_ptr 确实具有令人难以置信的性能,尽管您可以变得更好,但它可能是您的最佳选择:它有效。

不过,您可以查找另一个 Boost 智能指针:boost::intrusive_ptr

这是以前述为代价的:weak_ptr 并且作为交换允许为计数器和对象分配一个内存。将两者打包在一起会产生少量的性能提升。

如果您没有循环引用,请尝试检查一下,它可能就是您要查找的内容。

【讨论】:

  • 打包也可以用make_shared函数实现。
  • @ronag:如果我没记错的话,make_shared 仍然进行 2 次分配,因为 countershared_ptr 池和 weak_ptr 池之间共享,并且独立生活。 make_shared 打包的是删除器和实际分配的对象。不过我可能弄错了,在提升源中跋涉肯定不是我最喜欢的消遣时间。
【解决方案3】:

侵入式智能指针通常比普通智能指针更有效,但比哑指针更容易。例如,查看boost::intrusive_ptr<T>

【讨论】:

    【解决方案4】:

    如果对象不相互引用,手动引用计数可能值得尝试。添加到列表或从列表中删除时会产生更多成本,但实际对象访问不会产生开销。 (如果你弄错了,诊断起来会很痛苦,所以我建议小心把它弄对。)

    如果操作之间存在死区时间,请考虑一种垃圾收集。维护所有对象的列表(侵入性列表可能会这样做)。当您有空闲时,将其与其他列表交叉引用;任何不在列表中的对象都可以被删除。您不需要额外的数组来执行此操作(只需一个全局计数器和每个对象上的最后一个计数器),因此它可以相当有效。

    另一种选择是使用提供对底层指针的访问的智能指针。如果您想避免大量调用重载的operator-> 的开销,那么这可能值得一试。将智能指针存储在列表中(这会为您进行生命周期管理),然后在运行对象时,您可以检索每个对象的原始指针并使用它进行操作(因此您不会产生任何重载 operator-> 的开销ETC。)。例如:

    std::vector<smart_ptr<T> > objects;
    
    if(!objects.empty()) {
        smart_ptr<T> *objects_raw=&objects[0];
        for(size_t n=objects.size(),i=0;i<n;++i) {
            T *object=objects_raw[i].get_ptr();
    
            // do stuff
        }
    }
    

    这是我个人更喜欢的一种方法。长期存储得到一个智能指针,短期存储得到一个普通指针。对象的生命周期很容易管理,而且您不会遇到 1,000,000 个微小的开销(对于保持调试构建的可运行性比对于发布构建更重要,但它很容易增加浪费的时间)。

    【讨论】:

      猜你喜欢
      • 2013-04-25
      • 1970-01-01
      • 2019-06-30
      • 2012-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多