char* mem = new char[CHUNK_SIZE * OBJ_COUNT];
std::list<char*> free_chunks;
for (char* c = mem, int i = 0; i < OBJ_COUNT; ++i)
{
free_chunks.push_back(c);
c += CHUNK_SIZE;
}
正在获取要分配的新区块:
if(free_chunks.size() > 0)
{
char* c = free_chunks.back();
free_chunks.pop_back();
return c;
}
else{ // Error, not enough memory... }
pool.reserve(capacity); //std::vector<Object*>
for (int i = 0; i < capacity; ++i) {
pool.push_back(new Object());
}
for (int i = 0; i < capacity-1; ++i) {
pool[i]->setNext(pool[i+1].get());
}
first_available = pool[0].get(); //variable where you store first free object
pool[capacity-1]->setNext(NULL);
3条答案
按热度按时间ktecyv1j1#
这个解决方案使用额外的内存(这可能是你想要的,也可能不是你想要的),如果你试图连续两次释放一个块,你也会遇到问题。
预先分配足够的内存。将内存分成块,每个对象一个。保留一个空闲块列表。当你分配一个新对象时,从空闲块列表的顶部选择一个块。当你释放一个对象时,将它的块追加到空闲块列表中。这两个操作都是O(1)。
它看起来像这样:
姓名首字母:
正在获取要分配的新区块:
在解除分配后返回块:
pnwntuvh2#
你可以用O(1)的对象检索来实现简单的对象池。但是你的对象需要有指向下一个对象的内部指针。在池的构造函数中有一些预先计算:
则
getObject
方法为:希望有帮助。
kqlmhetl3#
对于一般的内存分配问题,您只有碎片,其中请求任意长度的块。这里的问题是给定以下内存布局:
(其中
@
表示正在使用,-
表示空闲)虽然总共有6个空闲块,但您不能分配4个连续的块。因此,您必须增加受管理空间的总量(如果可能)。此外,在此一般情况下,决定选择哪个地址并非微不足道,并且有几个策略(最先匹配、最差匹配等)会影响碎片的程度。
在您的示例中,问题要简单得多,因为您知道要分配的区域大小始终为某个整数
k
(比如k = sizeof(T)
)。这意味着你总是会有完美的拟合块,你组织就像你喜欢的。简单地处理空闲空间,就好像它是一个链表一样,并且总是使用链表中的第一项来响应内存分配请求。现在,如果你想在大块中分配以摊销分配,你可以保持一个额外的计数器,计数在一个特定的块中使用了多少个插槽,以便在它为空时释放该块(如果你想缩小插槽库的话!)
如果你坚持总是从最常用的块中分配新的内存块,你可以使用一个额外的列表来指示哪个块是最满的。因为你总是只能将已用插槽的数量改变一个,你可以保持该列表以
O(1)
排序,只需交换相邻的节点。