C++ 具有堆栈和动态分配的容器

C++ 具有堆栈和动态分配的容器,c++,optimization,stl,containers,C++,Optimization,Stl,Containers,是否有一个容器对少量元素使用本地缓冲区,并且仅当元素数量超过某个限制时才使用堆分配?与大多数std::string实现类似 背景 容器在以下(简化)上下文中使用: Foo-Foo;//一些数据 向量标记;//接收“标记”项目 //第一次通过:覆盖someList中的所有项目 对于每个(someList中的HandlerPtr h) { h->HandleFoo(foo);//foo可能在此处被标记或未标记 if(foo.taged()) 标记。推回(h); } 对于(自动itr=taged.r

是否有一个容器对少量元素使用本地缓冲区,并且仅当元素数量超过某个限制时才使用堆分配?与大多数
std::string
实现类似


背景

容器在以下(简化)上下文中使用:

Foo-Foo;//一些数据
向量标记;//接收“标记”项目
//第一次通过:覆盖someList中的所有项目
对于每个(someList中的HandlerPtr h)
{
h->HandleFoo(foo);//foo可能在此处被标记或未标记
if(foo.taged())
标记。推回(h);
}
对于(自动itr=taged.rbegin();itr!=taged.end();++itr)
{
// ...
}
此代码部分具有较高的调用频率,但标记项的情况非常少见,
someContainer
中的项数通常较低,但未绑定。我不能轻易地使用预先分配的“更全局”缓冲区。目标是避免频繁的分配


呼叫频率

  • 通用:没有项目被标记。向量是好的
  • 常见:只有少数项目中的一项被标记。导致我想要避免的高频率分配
  • 非常罕见,但必须得到支持:someList在第一次通过时会增长,项目数量不可预测,但仍然很低

    • 没有标准容器可以保证这种行为。但是,如果您能胜任,可以创建一个自定义的STL兼容分配器类,该类从小型堆栈缓冲区中提取用于小型分配的数据,并且仅当请求的分配大小超过堆栈缓冲区的大小时才执行堆分配。您可以插入自定义分配器类作为
      std::vector
      的第二个模板参数


      有关创建自定义分配器的信息,请阅读。

      没有标准容器可以保证这种行为。但是,如果您能胜任,可以创建一个自定义的STL兼容分配器类,该类从小型堆栈缓冲区中提取用于小型分配的数据,并且仅当请求的分配大小超过堆栈缓冲区的大小时才执行堆分配。您可以插入自定义分配器类作为
      std::vector
      的第二个模板参数


      有关创建自定义分配器的信息,您应该阅读。

      尽管不能保证这一点,但大多数
      std::string
      将实现
      小字符串优化
      ,就是这样(使用VC++10最多可存储8或16个字符)


      我没有见过向量>代码>,并且一直想知道为什么,但是即将到来的C++标准将有助于使用<代码> STD::AligNeDySturie< /Cord>和<代码>对齐< <代码> >。通过这种方式,我们将能够获得正确对齐的原始内存,并使用一些默认数量的“堆栈”内存构建容器。

      尽管不能保证这一点,但大多数
      std::string
      将实现
      小字符串优化
      ,就是这样(使用VC++10,最多可存储8或16个字符)


      我没有见过向量>代码>,并且一直想知道为什么,但是即将到来的C++标准将有助于使用<代码> STD::AligNeDySturie< /Cord>和<代码>对齐< <代码> >。通过这种方式,我们将能够获得正确对齐的原始内存,并使用一些默认数量的“堆栈”内存构建容器。

      要使用静态还是堆栈分配?有关堆栈分配,请参见@nimrodn:stack allocation可能是我想要的更好的描述(固定标题)。i、 e.可以存储在容器实例中的有限数量的元素(无需额外分配),如果不够,则使用堆分配。
      std::vector
      在至少插入一个元素之前不会分配任何内存。是否使用静态或堆栈分配?有关堆栈分配,请参见@nimrodn:stack allocation可能是我想要的更好的描述(固定标题)。i、 e.可以存储在容器实例中的有限数量的元素(无需额外分配),如果这还不够,则使用堆分配。
      std::vector
      在至少插入一个元素之前不会分配任何内存。您也可以尝试.reserve()在向量中保留较小的空间,但“够了“大多数时候。如果向量的策略是从1开始,并且无论当前大小都使用相同的调整大小策略,那么这可能会避免重新分配。@Karl:常见的情况是容器将保持为空。保留将不利于此,因为它将始终分配动态内存。在C++0x中,这当然是解决方案,但是,如果我没有记错的话,C++03分配器不应保持未在分配器的所有实例之间共享的状态(也就是说,可能会要求相同类型的任何其他分配器销毁/取消分配,即使这两个实例完全不相关)。实际上,我认为应该可以这样做:)您也可以尝试。reserve()在向量中保留一定量的空间,虽然空间很小,但大多数情况下“足够”。如果向量的策略是从1开始,并且无论当前大小都使用相同的调整大小策略,那么这可能会避免重新分配。@Karl:常见的情况是容器将保持为空。保留将不利于此,因为它将始终分配动态内存。在C++0x中,这当然是解决方案,但是,如果我没有记错的话,C++03分配器不应保持未在分配器的所有实例之间共享的状态(也就是说,即使两个实例完全不相关,也可能会要求相同类型的任何其他分配器销毁/取消分配)。在实践中,我认为它应该可以工作:)向量的大小通常不会超过三个指针的大小。考虑到你还需要存储一些内务管理数据,这个空间能容纳多少数据?@客人我想这取决于你是否使用更高的空间
      Foo foo;                     // some data
      vector<HandlerPtr> tagged;   // receives "tagged" items
      
      // first pass: over all items in someList
      for each(HandlerPtr h in someList)
      {
        h->HandleFoo(foo);         // foo may become tagged or untagged here
        if (foo.Tagged())
          tagged.push_back(h);
      }
      for(auto itr=tagged.rbegin(); itr!=tagged.end(); ++itr)
      {
        // ...
      }