如同进程池和线程池一样,使用内存池也是为了提高效率。
如果不使用内存池,那么频繁的malloc小字节内存不仅会降低运行效率,而且也会产生内存碎片,因此合理使用内存池会让进程执行地又快又好。
简单的内存池代码如下:
//用链表实现一个简单的内存池
template <class type>
class memory_pool
{
public:
memory_pool()
:link(Node()), flag(Flag())
{}
//释放空间
~memory_pool()
{
Flag *tmp = nullptr;
while (flag.next != nullptr)
{
tmp = flag.next;
flag.next = tmp->next;
free(tmp->ptr);
free(tmp);
}
}
//分配空间
void *alloc()
{
if (nullptr == link.next)
drop_water();
Node *node = link.next;
link.next = link.next->next;
return node;
}
//回收空间
void dealloc(void *ptr)
{
Node *tmp = (Node *)ptr;
tmp->next = link.next;
link.next = tmp;
}
private:
typedef struct node//链表节点
{
node(struct node *next = nullptr)
:next(next)
{}
struct node *next;
}Node;
typedef struct flag//记录每次malloc的地址
{
flag(void *ptr = nullptr)
:ptr(ptr), next(nullptr)
{}
void *ptr;
struct flag *next;
}Flag;
void drop_water()//给内存池注水,每次注type * 20个字节
{
void *space = malloc(sizeof(type) * 20);
if (nullptr == space)
throw bad_alloc();
//添加flag节点
Flag *tmp = new Flag(space);
tmp->next = flag.next;
flag.next = tmp;
//把20个块链接到链表上
link.next = (Node *)space;
Node *ptr = link.next;
Node *next = nullptr;
for (int i = 1; i <= 19; ++i)
{
next = (Node *)((char *)ptr + sizeof(type));
ptr->next = next;
ptr = next;
}
ptr->next = nullptr;
}
Node link;//链表
Flag flag;//标记
};
原理如图:
1.链表为空时分配大块内存并链接到链表上。
2.从链表中分配小块内存出去。
3.把小块内存回收到链表中来。