【c++】内存池的实现

使用内存池的原因:

在c++开辟空间和释放空间使用的是new和delete,而new和delete是对内存的操作,对内存进行操作必然需要从用户态转到入内核态,系统在接收到分配一定大小内存请求时,首先查找内部维护的内存空闲块表,并且需要一定的算法找到合适的内存块,由此频繁的new和delect会降低效率,并且在内存中会产生外碎片。默认的内存管理函数还考虑到多线程的应用,需要在每次分配和释放内存时加锁,同样有增加开销。为了解决这些问题,就有了内存池的概念。。。。

 

 

内存池的介绍以及优点:

内存池,池的概念就是一组资源的集合,简单来说,内存池就是实现一种对内存的管理机制。使用内存池有以下的优点

1)对于需要频繁分配释放固定大小的内存对象时,不需要复杂的分配算法和多线程保护,也不需要维护内存空闲表的额外开销。

2)一次会开辟大量连续的空间作为内存池,提高了程序的性能,不会产生大量的外碎片,同时不用多次进入内核态。

内存池的解析

这里使用静态链表实现内存池,什么是静态链表呢,就是以数组的形式存在能做链表的事情,如图是实现内存池的图解:

pool:指向内存池的一个标识,指向内存池中第一块未使用的内存块

数据域:内存块要被使用时,需要存放的数据

指针域:指向下一块未使用的内存块

alloc():在pool为NULL的时候,实现开辟一块大的内存;并且实现内存块的分配

dealloc():实现内存块释放后,归还到内存池中;

图解内存管理机制的过程:

 

 

 

完整的代码实现:

#include <iostream>
template <typename T>
class Memory_Pool
	//内存池
{
public:
	void* alloc(size_t size)
		//实现对空间的开辟(内存块的使用)
	{
		if(pool == NULL)
		{
			pool = (Node*)new char[(size + 4) * 10]();//开辟一个大的内存,里面有十个内存块
			Node* pcur = pool;
			for(pcur;pcur < pool + 10 -1;pcur = pcur + 1)
			{
				pcur->pnext = pcur + 1;//指针域使得各个内存块完成连接
			}
			pcur->pnext = NULL;//最后一个内存块的指针域肢痿空
			Node* prt = pool;
			pool = pool->pnext;//不能是pool = pool + 1 因为可能下一个内存块已经使用,而pnext可以指向下一个未使用的内存块
			return prt;
		}
	}
	void* dealloc(void* ptr)
		//实现对空间的释放(内存块的归还)使用头插的方法
	{
		Node* prt = pool;
		prt->pnext  = pool;
		pool = prt;
	}
private:
	class Node
		//内存池中的内存块
	{
	public:
		Node(T val = T()):mdata(val),pnext(NULL){}
	public:
		T mdata;//数据域
		Node* pnext;//指针域
	};
	static Node* pool;//指向内存池的静态指针,多个对象共用一个内存池
};
template<typename T>
typename Memory_Pool<T>::Node* Memory_pool<T>::pool = NULL;//对pool进行初始化;typename的作用是告诉编译器Node*是一个类型

class Test
{
public:
	Test(int a):ma(a){}
	void* operator new(size_t size)
	{
		return mp.alloc(size);
	}
	void operator delete(void* ptr)
	{
		mp.dealloc(ptr);
	}
private:
	int ma;
	static Memory_Pool<Test> mp;
};
Memory_Pool<Test> Test::mp;
int main()
{
	Test* ptest = NULL;
	for(int i = 0;i < 20;i++)
	{
		ptest = new Test(20);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/QX_a11/article/details/89303590