C++实现简单内存池

在探讨内存池前,我们需要回顾一下池的相关知识!

池(pool):一组资源的集合。

这组资源在服务器启动之初就被完全创建好并初始化,这称为静态资源分配。当服务器进入正式运行阶段,即开始处理客户请求的时候,如果处理该请求需要相关的资源,就可以直接从池中获取,无需动态分配。

很显然,直接从池中取得所需资源比动态分配资源的速度要快很多,因为分配系统资源的系统调用都是很费时间的。当服务器处理完一个客户请求后,就可以把相关资源放回池中,无需执行系统调用来释放资源。

从最终的效果来看,池相当于服务器管理系统资源的应用层设施,它避免了服务器对内核的频繁访问。

根据不同的资源类型,池可以分为多种,常见的池有:内存池(划重点!!)、进程池、线程池、连接池。


我们在编写程序的过程中,经常要向系统申请内存空间,有时申请的多,有时申请的少,用完了之后又还给系统。当下次要申请空间时,又重复前面的操作。这样来来回回次数多了,不仅你烦了,内存也烦了,因为你频繁的申请空间、释放空间,导致产生了很多的内存碎片(这里的叫外碎片),而且这样的操作效率还不高。

【插播一条外碎片的知识:外碎片指的是还没有被分配出去(不属于任何进程),但由于太小了无法分配给申请内存空间的新进程的内存空闲区域。外碎片是除了任何已分配区域或页面外部的空闲存储块。这些存储块的总和可以满足当前申请的长度要求,但是由于它们的地址不连续或其他原因,使得系统无法满足当前申请。】

那么,怎么才能提高分配内存的效率,以及减少外碎片呢?内存池同志挥手示意。

请内存池同志做下自我介绍。

内存池:大家好,我叫内存池,我是从系统上分配出来的一部分资源,简单来说,就是在需要使用内存之前,先向系统申请好大好大的一块内存,这块内存就由我来管理和分配。等我想使用内存的时候,我就在内存池里面分一块出来用;等这块内存用完了我就又把它放回内存池里,这样内存循环使用。当内存池里所有内存块都被使用的时候,就再申请一块更大的内存块作为新的内存池。由于是我来回收,无需系统调用来回收,这样分配内存的效率就高一些,也能减少外碎片的产生

【内存池是一种内存分配方式。内存池的优点是可以有效的减少内存碎片化,分配内存更加快速,减少内存泄漏等优点。】

用C++实现简单内存池,这里采用的结构是静态链表。如下图:

该内存池可以实现自主的内存管理机制:

1. 分配内存:alloc 

(1)operator new

(2)构造

2. 回收内存:dealloc

(1)operator delete 

(2)析构

C++ 实现内存池过程,附代码:

const int MEM_SIZE = 10;
template<typename T>
class MEM_Pool
{
public:
	static MEM_Pool<T>* getInstance()
	{
		if (mmp == NULL)
		{
			mmp = new MEM_Pool<T>();
		}
		return mmp;
	}

	void* alloc(size_t size)  //分配内存
	{
		if (pool == NULL)
		{
			pool = (Node*)new char[(size + 4)*MEM_SIZE]();  //从系统开辟内存池
			Node* pCur = pool;  

            // 构造内存池内部结构(静态链表)
			for (pCur; pCur < pool + MEM_SIZE - 1; pCur = pCur + 1)
			{
				pCur->pnext = pCur + 1;
			}

            //将内存池最后一个内存块的pnext域指向NULL,当pool为NULL时,重新申请一块更大的内存
			pCur->pnext = NULL; 
		}

        //分配出去一个内存块使用
		void* rt = pool;
		pool = pool->pnext;  //pool始终指向下一个可用内存块
		return rt;
	}

	void dealloc(void* ptr)  //回收内存
	{
		if (ptr == NULL)
		{
			return;
		}
		Node* pptr = (Node*)ptr;  ///类型转换
		pptr->pnext = pool;  //将当前该内存块的pnext域指向pool
		pool = pptr;         //接着将当前该内存块的指针变为新的pool
	}

private:
	MEM_Pool()
	{
		pool = NULL;
	}

	MEM_Pool(const MEM_Pool<int>&);

	class Node
	{
	public:
		Node(T val = T()) :mdata(val), pnext(NULL){}
	public:
		T mdata;
		Node* pnext;
	};

	Node* pool;  //指向当前可用内存块
	static MEM_Pool<T>* mmp;
};

template<typename T>
MEM_Pool<T>* MEM_Pool<T>::mmp = NULL;

class CGoods
{ 
public:
	CGoods(std::string name, float price, int amount)
		:mname(name), mprice(price), mamount(amount)
	{}
	void* operator new(size_t size) 
	{
		return pmm->alloc(size);
	}
	void operator delete(void* ptr)
	{
		pmm->dealloc(ptr);
	}
private:
	std::string mname;
	float mprice;
	int mamount;
	static MEM_Pool<CGoods>* pmm;
};
MEM_Pool<CGoods>* CGoods::pmm = MEM_Pool<CGoods>::getInstance();

int main()
{
	CGoods* pgood1 = new CGoods("面包", 4.5, 100);
	CGoods* pgood2 = new CGoods("矿泉水", 2.0,100);

	delete pgood1;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值