如何完全管理像map这样的std容器的堆内存分配?

4
我对使用多个std map<int,int> 很感兴趣,并且我希望它们都可以从一个公共的内存池中分配元素。目前为止,根据我的阅读,我可以使用诸如Boost pool_alloc之类的自定义分配器来实现这一点。
我的问题是,尽管使用类似于Boost pool_alloc这样的工具来管理元素本身的分配,std map是否仍然会使用一些堆内存作为某种容器开销,而这些内存不会由boost pool_alloc进行管理?我在考虑与std map本身的使用相关的元素指针等问题。

你是在问包含指针的容器吗?抱歉问了这个问题,但我还没有理解到... - Stefan
@Stefan:不是包含指针的容器。考虑到自定义分配器将负责元素本身的分配,我想知道std::map所有容器内存开销是否也由自定义分配器覆盖。希望这能澄清我的问题。 - polemic
明白了。不行。具体的分配器负责为特定元素在堆上分配空间,而不是容器本身。如果您想改变这一点,您需要为您的特定容器重载operator new/delete。 - Stefan
1个回答

3

简短版

一个地图类型,如:

typedef std::map<
    int,
    int,
    less<int>,
    boost::pool_allocator<pair<const int, int> >
    > 
    AMapType;

我会使用boost::pool_allocators来分配所需的所有内容。初始结构可能在堆栈上创建。然而,具体的结构和数量取决于实现。

重新绑定分配器

通过使用allocator::rebind,可以实现上述功能。

所有符合std::allocator标准的分配器(如boost::pool_allocator)都提供了一个重新绑定模板结构,形式为:

template<class U> struct rebind{
   typedef AllocatorType<U> other;
};

这可以用于获取不同类型的相同类型的分配器:
typedef AllocatorOfOther AllocatorType::rebind<ADifferentType>::other;

gcc std::map内部结构

g++的std::map实现(我检查了4.7.3和4.1.1)完全由单个节点类型构建。这包括键值对以及rbTree结构所需的指针和颜色位。为了分配这些,它定义了一个Node分配器,使用用户提供的分配器中的rebind结构。这用于随着地图增长进行的所有分配。每个新节点都在单个分配中分配。

标准

我查阅了C++11标准,但没有找到任何规定如何分配此类结构的内容。要么我没有找到正确的部分,要么它没有被指定。不过,不使用用户给定的分配器似乎有点毫无意义。


只是想澄清一下:根据我的理解,rebind将元素T转换为某种Node<T>,带有额外的左右指针(或类似的内容)。这是否意味着,除了由std::map创建的Node元素本身之外,不会有其他分配产生? - polemic
所以,我做了和你一样的事情,但是我使用了 boost::pool_allocator< int >。那怎么可能行得通呢? - JHBonarius
1
@JHBonarius 很可能容器实现从未实际使用其原始类型的分配器,而总是首先将其重新绑定到某些其他类型。在这种情况下,模板参数中几乎任何类型都可以工作。 - PeterSW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接