C++ 防止STL容器中的内存释放

C++ 防止STL容器中的内存释放,c++,memory-management,stl,C++,Memory Management,Stl,我有一个STL容器(std::list),我一直在重复使用它。我的意思是我 将多个元素推入容器中 在处理过程中移除元素 清理容器 冲洗并重复多次 使用callgrind评测时,我看到大量调用new(malloc)和delete(free),这可能非常昂贵。因此,我正在寻找某种方法,最好预先分配相当多的元素。我还希望我的分配池继续增加,直到达到一个高水位线,并希望分配池继续挂起内存,直到容器本身被删除 不幸的是,标准分配器不断调整内存池的大小,所以我正在寻找一些分配器,它可以在不必编写自己的内存池

我有一个STL容器(std::list),我一直在重复使用它。我的意思是我

  • 将多个元素推入容器中
  • 在处理过程中移除元素
  • 清理容器
  • 冲洗并重复多次
  • 使用callgrind评测时,我看到大量调用
    new
    malloc
    )和
    delete
    free
    ),这可能非常昂贵。因此,我正在寻找某种方法,最好预先分配相当多的元素。我还希望我的分配池继续增加,直到达到一个高水位线,并希望分配池继续挂起内存,直到容器本身被删除

    不幸的是,标准分配器不断调整内存池的大小,所以我正在寻找一些分配器,它可以在不必编写自己的内存池的情况下执行上述操作

    是否存在这样的分配器?在哪里可以找到这样的分配器

    我使用GCC在Linux上工作,使用STLPort在Android上工作


    编辑:Placement
    新建
    没问题,我想最小化的是堆遍历,这很昂贵。我还希望我的所有对象尽可能靠近,以最大限度地减少缓存未命中。

    听起来您可能只是使用了错误类型的容器:对于列表,每个元素占用单独的内存块,以允许单独的插入/删除-因此列表中的每个添加/删除表单都需要单独的
    new()/删除()

    如果可以改用
    std::vector
    ,则可以在添加项目之前
    保留所需的大小

    对于删除,通常最好不要单独删除项目。只需调用容器上的
    clear()
    ,将其清空即可。它



    编辑:您现在已经在评论中明确表示,您的“在处理过程中删除元素”步骤是从列表中间删除元素,并且不能使迭代器无效,因此切换到向量是不合适的。我暂时不回答这个问题(为了评论线索!)

    你可以尝试使用测试你的应用程序,我在我的一些项目中看到了一些很好的改进(虽然手头没有数字,对不起)


    编辑:似乎代码/下载已移到那里:

    评论太短,因此我将发布我的想法作为答案

    在国际海事组织,在这种情况下,新建/删除只能来自两个地方

    我相信由于各种原因,
    std::list
    与通常的列表一样,是通过某种节点实现的。因此,元素的每次插入和移除都必须导致节点的新建/删除。此外,如果
    T
    类型的对象在c'tor/d'tor中有任何分配和解除分配,那么它们也将被调用

    通过在现有节点上重复而不是删除它们,可以避免重新创建标准内容。如果您想将其压缩到c级,可以使用and或

    尽管如此,对于创建的每个对象,都必须称为析构函数。我认为避免创建和破坏的唯一方法是在容器上重复时使用
    T::operator=
    ,或者如果适合您的情况,可以使用一些c++13
    移动
    东西。

    分配器是为与
    std::list
    一起使用而设计的

    该文档声称“如果您非常关心性能,请在处理诸如
    std::list
    之类的容器时使用
    boost::pool\u分配器
    ,在处理诸如
    std::vector
    之类的容器时使用
    boost::pool\u分配器


    请注意,
    boost::fast_pool_allocator
    是一个单例,默认情况下它从不释放分配的内存。但是,它是使用实现的,您可以通过调用静态函数
    boost::singleton_pool::release_memory()
    boost::singleton_pool::purge_memory()来释放内存

    new和delete可能是容器中包含的对象析构函数和构造函数,这使容器变得更加复杂unavoidable@fatih_k但是,只有当列表中包含指向动态分配对象的指针时,这才有效。我相信OP可能知道要避免这种情况。@Angew,只有当包含的元素是对象而不是指针时,才会调用对象的析构函数。容器不拥有指针的所有权Placement new可以,我只想最小化对MALOC和FRILI的调用,认为您应该查看这些分配器实例:-除了我想删除列表中间的元素,而没有内存拖曳:STD::vector将entail@doron内部的订单是否包含物质?如果没有,您只需将要删除的内容与最后一个元素交换,然后
    pop_back()
    。没有洗牌。@doron不过,记忆洗牌可能比你想象的要少。请看Bjarne Stroustrup解释向量vs列表的好处(从44:40开始)简言之,即使您删除了很多内容并插入了很多内容,列表中的线性搜索时间也完全支配着处理时间,因为对象分散在内存中,这会影响cpu缓存。@doron“除了我想删除列表中间的元素,而没有内存更新:STD::向量将带来”——你已经使用了一个分析器,所以只需测试一个测试,比较向量的洗牌疯狂速度到列表的分配疯狂。结果可能是令人惊讶的(并且可能粉碎你对Big-O符号的信任);).@doron那么这确实是一个完美的(如果不是唯一合理的话)一个
    std::list
    的用例,是你应该在对这个答案的第一次评论中提到的,而不是performance参数,因为前者是你不能使用
    std::vector
    的一个很难解释的原因,而不是一个要讨论的伪原因