C++ 映射分配节点打包?

C++ 映射分配节点打包?,c++,stl,memory-management,C++,Stl,Memory Management,我注意到VisualStudio(2010)的std::map实现为其红黑树中的每个节点分配了一个新的内存块。也就是说,对于映射中的每个元素,将通过操作符new。。。malloc使用VisualStudioSTL实现的std::map的默认分配方案 这对我来说似乎有点浪费:像std::vector实现在增长时过度分配一样,以“(小)n”块分配节点不是更有意义吗 因此,我想澄清以下几点: 我关于默认分配方案的断言是否正确 std::map的“所有”STL实现都是这样工作的吗 std中是否有任何东

我注意到VisualStudio(2010)的std::map实现为其红黑树中的每个节点分配了一个新的内存块。也就是说,对于映射中的每个元素,将通过
操作符new。。。malloc
使用VisualStudioSTL实现的std::map的默认分配方案

这对我来说似乎有点浪费:像std::vector实现在增长时过度分配一样,以“(小)n”块分配节点不是更有意义吗

因此,我想澄清以下几点:

  • 我关于默认分配方案的断言是否正确
  • std::map的“所有”STL实现都是这样工作的吗
  • std中是否有任何东西阻止std::map实现将其节点放入内存块中,而不是(通过其分配器)为每个节点分配新的内存块?(复杂性保证等)

注意:这与过早优化无关。如果它是关于优化,那么它是关于应用程序是否存在(std::)映射内存碎片的问题,除了使用使用内存池的自定义分配器,还有其他选择吗?这个问题不是关于自定义分配器,而是关于map实现如何使用其分配器。(或者我希望是这样。)

我很确定我从未见过试图将多个节点合并到单个分配块中的
std::map
的实现。至少现在我想不出它不能工作的原因,但我认为大多数实现者会认为它是不必要的,并将内存分配的优化留给分配器,而不是在
映射中过多地担心它


诚然,编写大多数自定义分配器是为了更好地处理大量小块的分配。通过编写
map
(当然还有
set
multiset
、和
multimap
)来使用更大的分配,您可能会使绝大多数此类优化变得不必要。OTOH,考虑到优化小数据块分配的分配器很容易/常见/广泛可用,可能也没有太多动机以这种方式更改
map
实现。

我认为您唯一不能做的事情是使迭代器无效,如果必须重新分配存储,您可能必须这样做。话虽如此,我见过使用std::map接口中包装的单个对象排序数组的实现。当然,这是出于某种原因


实际上,您所能做的只是使用自定义分配器实例化您的std::map,它将以一种特殊的、非浪费的方式为新节点找到内存。

当您将元素插入map时,可以保证现有迭代器不会失效。因此,如果您在两个节点A和C之间插入一个元素“B”,而这两个节点恰好是连续的,并且位于同一堆分配区域内,那么您不能将它们洗牌以腾出空间,而B必须放在其他位置。我不认为这有什么特别的问题,除了管理这样的复杂性会扩大实现。如果删除元素,迭代器也不会失效,这意味着任何内存分配都必须挂起,直到其中的所有节点都被删除。您可能需要在每个“膨胀节点”/“向量”中包含一个freelist,不管您想叫它什么,它至少会有效地重复new/delete当前为您执行的一些耗时操作。

您的断言对于std::map的大多数实现都是正确的

据我所知,标准中没有任何内容阻止地图使用您描述的分配方案。然而,您可以通过自定义分配器获得所描述的内容,但是在所有映射上强制使用该方案可能是浪费。因为map并没有关于如何使用它的先验知识,某些使用模式可能会阻止大部分未使用块的释放。例如,假设一次为4个节点分配了块,但一个特定的映射填充了40个节点,然后删除了30个节点,最坏的情况是每个块只剩下一个节点,因为映射无法使指向最后一个节点的指针/引用/迭代器无效

这对我来说似乎有点浪费。像std::vector实现在增长时过度分配一样,以“(小)n”块分配节点不是更有意义吗

有趣的是,我的看法完全不同。我觉得这是合适的,而且不会浪费任何内存。至少在Windows(MS VS 2008)、HP-UX(带STLport的gcc)和Linux(不带STLport的gcc)上使用defaul STL分配器。重要的是,这些分配器确实关心内存碎片,而且似乎可以很好地处理这个问题。例如,在Windows上查找
低碎片堆
,或在HP-UX上查找SBA(小型块分配器)。我的意思是,频繁地一次只为一个节点分配和释放内存并不一定会导致内存碎片。我在自己的一个程序中测试了
std::map
,它确实没有导致这些分配器出现任何内存碎片。

这是我关于默认值的断言 分配方案是否正确

我有MS VisualStudio 2008,其std::map的行为方式与此相同。在HP-UX上,我使用带或不带STLport的gcc,它们的STL映射似乎有相同的方法为
std::map


中的节点分配内存

std里有什么东西吗 防止std::map实现 将其节点放入 内存,而不是分配一个新的 内存块(通过其分配器) 对于每个节点

如果可能的话,从调整平台上的默认分配器开始。这里引用《世界卫生组织》一书的作者是很有用的

。。。首先我写了一些 专用