【问题标题】:container with stack and dynamic allocation具有堆栈和动态分配的容器
【发布时间】:2011-05-23 07:59:28
【问题描述】:

是否有容器对少量元素使用本地缓冲区,仅在元素数量超过一定限制时才使用堆分配?类似于大多数 std::string 实现所做的。


背景

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

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)
{
  // ...
}

此代码部分调用频率很高,但标记一个项目的情况很少见,someContainer 中的项目数通常很少但未绑定。我不能轻易使用预先分配的“更全局”缓冲区。目标是避免频繁分配。


来电频率

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

【问题讨论】:

  • 您想使用静态分配还是堆栈分配?堆栈分配见stackoverflow.com/questions/354442/…
  • @nimrodn:堆栈分配可能是对我想要的更好的描述(固定标题)。即可以存储在容器实例中的元素数量有限(无需额外分配),如果这还不够,则使用堆分配。
  • std::vector 在插入至少一个元素之前不会分配任何内存。

标签: c++ optimization stl containers


【解决方案1】:

没有标准的容器可以保证这种行为。但是,如果您愿意,您可以创建一个自定义的 STL 兼容分配器类,该分配器类从小堆栈缓冲区中提取小分配,并且仅在请求的分配大小超过堆栈缓冲区的大小时执行堆分配。您可以插入您的自定义分配器类作为std::vector&lt;T, Alloc&gt; 的第二个模板参数。

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

【讨论】:

  • 您也可以尝试 .reserve() 在向量中保留一小部分空间,但大多数情况下“足够”。如果您的向量的策略是从 1 开始并使用相同的大小调整策略而不考虑当前大小,那么这可能会避免重新分配。
  • @Karl:一个常见的情况是容器将保持为空。保留对此不利,因为它总是会分配动态内存。
  • 在 C++0x 中这当然是解决方案,但是如果我没记错的话,C++03 分配器不应该维护未在分配器的所有实例之间共享的状态(即,任何其他分配器即使两个实例完全不相关,也可以要求相同的类型销毁/释放)。在实践中,我认为它应该有效:)
【解决方案2】:

虽然不能保证,但大多数std::string 将实现Small String Optimization,就是这样(VC++10 最多可以存储 8 或 16 个字符)

我还没有看到vectors 这样做,并且一直想知道为什么,但是即将推出的 C++ 标准将通过 std::aligned_storagealignof 促进这一点。通过这种方式,我们将能够正确对齐原始内存并使用一些默认数量的“堆栈”内存构建容器。

【讨论】:

  • 向量的大小通常不超过三个指针的大小。考虑到您还需要存储一些管理数据,这个空间可以容纳多少数据?
  • @visitor:我想这取决于您是否使用指针的较高位来保留此类数据:) 但我个人愿意拥有一个缓冲区 vector 类。复制vector 的成本与复制3 个指针的成本有很大不同,因为它涉及动态分配(因此调用allocate)和现有数据的深层复制。因此,我的看法是,简单地保留一些额外的空间会更便宜。 vector&lt;Element, 4&gt; 例如。但是我知道没有这样的容器,但我可能会在家里尝试一下,虽然它总是很难达到 STL 的效率。
  • @Mattieu:很难匹配 - 确切地说,尤其是效率+灵活性的组合。为我的特殊情况制作一些东西很容易,但这会带来很多限制,这并不好笑。
  • @peterchen:这也是真的,但即使在纯粹的效率方面,我的代码也经常比 STL 慢,即使我有理论上的高地(比如不在堆上分配)。我猜这就是“衡量标准”发挥作用的地方:D
猜你喜欢
  • 2019-05-17
  • 2012-07-28
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
  • 2012-03-02
  • 2023-04-02
  • 2012-03-19
  • 2010-12-11
相关资源
最近更新 更多