C++ 如何显式管理异构类型(和大小)的多个池分配器?
场景:我有一个G类,它(通常)由数千个从N类派生的对象组成。所有这些对象都有一个定义良好的生命周期。首先,构造一个对象G,然后添加N个派生对象,然后使用G进行一些计算,这不会改变N个派生对象,然后G超出范围,并且使用它,组成N个派生对象。N派生对象依次包含指向添加到同一G对象的其他N派生对象的指针或标准容器。G表示具有异构节点的图 我的目标是:C++ 如何显式管理异构类型(和大小)的多个池分配器?,c++,memory-management,boost,c++11,C++,Memory Management,Boost,C++11,场景:我有一个G类,它(通常)由数千个从N类派生的对象组成。所有这些对象都有一个定义良好的生命周期。首先,构造一个对象G,然后添加N个派生对象,然后使用G进行一些计算,这不会改变N个派生对象,然后G超出范围,并且使用它,组成N个派生对象。N派生对象依次包含指向添加到同一G对象的其他N派生对象的指针或标准容器。G表示具有异构节点的图 我的目标是: 最小化分配每个N派生对象的成本 最大化属于同一个G对象的N个派生对象的引用位置 通过为所有N个派生对象取消分配单个块,将取消分配的成本降至最低 为了能够
struct DataUnit { map<int,string> m; list<int> l; }
结构数据单元{map m;list l;}
我如何确保,对于DataUnit的每个实例,都有一个单独的池,从中分配m和l的内部成分?如果我将一个自定义分配器传递给map和list,m和l将获得该容器的独立实例。我最初认为我可以使用get_allocator()用我的aerena/pool初始化分配器。。。但是,遗憾的是,在vector的默认构造函数返回之前调用了allocate()。。所以我不能这么做
更奇怪的是,我发现,在涉足boost::container一段时间后。。。vanilla std容器有一个get_分配器()(在MSVC 2010和2012以及g++4.6.3上),这表明这些上下文中的标准库具有类似于boost::container的有状态分配器支持
不幸的是,对于我最初的问题,我仍然没有可行的解决方案(尽管我现在可以更雄辩地表达出来)
更新2
谢谢你,pmr,如果你把你最后的评论归类为答案,我会给你一个“正确答案”。)在找到boost::container之后,我的问题是,我希望它的文档能够明确说明任何新功能,比如在构造时传递分配器对象。。。我没有正确检查boost::container源代码。我现在确信,容器为我上面提到的所有问题提供了一个非常优雅和直观的解决方案(如果文档不完整的话)。再次感谢 警告:完全未测试的代码。我不知道它是哪种“惯用语”——但下面1.5页的代码应该可以解决您的问题
class GraphNodeAllocator
{
struct CMemChunk
{
CMemChunk* pNext;
BYTE* data()
{
return static_cast<BYTE*>( static_cast<void*>( this + 1 ) );
}
};
CMemChunk* m_pChunk; // Most recently allocated a.k.a. current chunk
BYTE* m_pFirstByte; // First free data byte within the current chunk
size_t m_freeBytes; // Count of free bytes within the current chunk
static const size_t cbChunkAlloc = 0x10000; // 65536 bytes per single allocation
static const size_t cbChunkPayload = cbChunkAlloc - sizeof( CMemChunk );
void* Allocate( size_t sz )
{
if( sz > cbChunkPayload )
return NULL;
if( m_freeBytes >= sz )
{
// Current chunk has the space
m_freeBytes -= sz;
void* res = m_pFirstByte;
m_pFirstByte += sz;
return res;
}
// Need a new chunk
CMemChunk* pChunk = static_cast< CMemChunk* >( malloc( cbChunkAlloc ) );
if( NULL == pChunk )
return NULL;
pChunk->pNext = m_pChunk;
m_pChunk = pChunk;
m_pFirstByte = m_pChunk->data();
m_freeBytes = cbChunkPayload;
return Allocate( sz );
}
public:
inline GraphNodeAllocator(): m_pChunk( NULL ), m_pFirstByte( NULL ), m_freeBytes( 0 ) { }
inline ~GraphNodeAllocator()
{
while( NULL != m_pChunk )
{
CMemChunk* pNext;
pNext = m_pChunk->pNext;
free( m_pChunk );
m_pChunk = pNext;
}
}
template<typename E>
inline E* newNode()
{
void* ptr = Allocate( sizeof( E ) );
if( NULL == ptr ) return NULL;
return ::new( ptr ) E();
}
};
类GraphNodeAllocator
{
结构CMemChunk
{
CMemChunk*pNext;
字节*数据()
{
返回static_cast(static_cast(this+1));
}
};
CMemChunk*m_pChunk;//最近分配的又称当前块
BYTE*m_pFirstByte;//当前块中的第一个可用数据字节
size\u t m\u freeBytes;//当前块中的可用字节计数
静态常量大小\u t cbChunkAlloc=0x10000;//每次分配65536字节
静态常量大小\u t cbChunkPayload=cbChunkAlloc-sizeof(CMemChunk);
无效*分配(大小)
{
如果(sz>cbChunkPayload)
返回NULL;
如果(m_freeBytes>=sz)
{
//当前块具有空间
m_freeBytes-=sz;
void*res=m_pFirstByte;
m_pFirstByte+=sz;
返回res;
}
//需要一块新的吗
CMemChunk*pChunk=static_cast(malloc(cbChunkAlloc));
if(NULL==pChunk)
返回NULL;
pChunk->pNext=m_pChunk;
m_pChunk=pChunk;
m_pFirstByte=m_pChunk->data();
m_freeBytes=cbChunkPayload;
收益分配(sz);
}
公众:
内联GraphNodeAllocator():m_pChunk(NULL)、m_pFirstByte(NULL)、m_freeBytes(0){}
内联~GraphNodeAllocator()
{
while(NULL!=m_pChunk)
{
CMemChunk*pNext;
pNext=m_pChunk->pNext;
免费(m_pChunk);
m_pChunk=pNext;
}
}
模板
内联E*newNode()