内存池的设计及其思想

先给出一段简单的代码

#include <iostream>
using namespace std;//为 using 指示符,其中 namespace 为名字空间作用域
                    //建议不用这个指示符,可在需要的地方加 std 的作用域 

void* operator new(size_t size) //size 代表总字节个数
{
	void* ptr = malloc(size);
	cout << "operator new: " << ptr << endl;
	return ptr;
}

void operator delete(void* ptr)
{
	cout << "operator delete: " << ptr << endl;
	free(ptr);
}

int main()
{
	int *p = new int;
	delete p;         //直接调用我们写好的 operator new(开辟空间) 和 
                          //operator delete (释放空间),没有初始化和释放资源
	return 0;
}

平时使用的 new 和 delete 有下面两个功能

new 1.开辟空间 2.初始化       delete 1.释放资源 2.释放空间

而这两个函数的功能为: operator new 开辟空间        operator delete 释放空间

 

思考:为什么要自己编写这两个函数?

new作为用户程序的关键字,调用系统开辟空间的接口,系统API交给一个文件或者管理系统,操控底层的硬件资源BSP。

所以new的过程是从用户态到内核态,其缺点一 :效率低;

如果申请3个字节,系统将分配4个字节,导致1个字节不可用,所以频繁调用易产生碎片,这是缺点二。

 

所以这两个函数 operator new  ,operator delete 实现了一个自己的内存管理方案(即内存池。池:一组资源的集合)             

 

内存池:怎样把资源分配出去?怎样把资源回收回来?内存池的设计如下:

  

 

//结合链队写一个简单内存池(意义不大) 之后再写一个通用内存池
const int MEM_POOL_SIZE = 10;
template<typename T>
class Queue//只有在new QueueItem()才会开辟内存池
{
public:
	Queue()
	{
		pfront = prear = new QueueItem(0);
	}
	~Queue()//链怎么释放节点
	{
		QueueItem* pCur = pfront;
		QueueItem* pNext = pfront;
		while(pCur != NULL)
		{
			pNext = pCur->pnext;
			delete pCur;
			pCur = pNext;
		}
		pfront = prear = NULL;
	}
	void push(T val)//入队 
	{
		QueueItem* pnewnode = new QueueItem(val);
		prear->pnext = pnewnode;
		prear = pnewnode;
	}
	void pop()//出队
	{
		if(!IsEmpty())
		{
			QueueItem* pCur = pfront->pnext;//有头结点,pCur指向第一个数据节点
			pfront->pnext = pCur->pnext;//让头结点指向第二个数据节点
			delete pCur;
		}
	}
	T front()//获取队头元素
	{
		if(!IsEmpty())
		{
			return pfront->pnext->mdata;
		}
	}
	T back()//获取队尾元素
	{
		if(!IsEmpty())
		{
			return prear->mdata;
		}
	}
private:
	bool IsEmpty()
	{
		return pfront == prear;
	}
	class QueueItem
	{
	public:
		QueueItem(T val = T()):mdata(val),pnext(NULL){} 
		void* operator new(size_t size)
		{
			if(pool == NULL)
			{
				pool = (QueueItem*)new char[size * MEM_POOL_SIZE];
				QueueItem* pCur = pool;
				for(pCur;pCur < pool + MEM_POOL_SIZE - 1;pCur++)
				{
					pCur->pnext = pCur + 1;
				}
				pCur->pnext = NULL;
			}
			QueueItem* rt = pool;
			pool = pool->pnext;
			return rt;
		}
		void operator delete(void* ptr)
		{
			if(NULL == ptr)
			{
				return;
			}
			QueueItem* p = (QueueItem*)ptr;
			p->pnext = pool;
			pool = p;
		}
	public:
		T mdata;//数据域
		QueueItem* pnext;//指针域
		static QueueItem* pool;
	};
	QueueItem* pfront;//队头指针
	QueueItem* prear;//队尾指针
};
template<typename T>
typename Queue<T>::QueueItem* Queue<T>::QueueItem::pool = NULL;//静态变量一定在类外初始
//                 QueueItem类型(加关键字typename)    QueueItem 是普通的类,不需要加模板类型参数

int main()
{
	Queue<int> que;
	for(int i = 0;i < 10;i++)
	{
		que.push(i+1);
	}

	return 0;
}

 

  

 

 

猜你喜欢

转载自blog.csdn.net/TUJI67/article/details/89344865