内存池--队列

传统的内存分配:

1.外碎片
在这里插入图片描述
当我们只有红色部分申请4字节的内存时,其他的都使用8字节的内存,包括后序的申请都是8字节的空间,那么这个4字节的内存就分配不出去了,这个时候4字节的内存就是外碎片

2.内碎片
大多都是内存对齐引起的,比如:

struct A
{
	int a;
	char b;
};

我们知道,在32位机器下,A的大小是8。所以在生成对象的时候是分配了8个字节的空间,但是里面只使用了5字节的内存空间,这就叫做内碎片。


为了实现自主的申请内存自主的释放内存,不借助系统的操作,提出来池的概念–内存池

  • 申请一块大的内存空间,然后后序的操作都是在这一块内存区域上,最后释放一次就好了。所以说现在只要申请一次,释放一次就可以了,到时候大的内存归还,就不容易产生内存碎片了。
  • 然后就是设计相应的数据结构,可以标识内存的分配状态:静态链表
    在这里插入图片描述
  • 因为底层是以链表的形式存在的,所以在申请内存的时候,会选择头部的空间,相当于头删,然后让头指针指向下一个节点;在释放内存的时候,相当于头插,并改变pool头指针的指向就可以了。

接下来我用内存池去实现队列:

#include <iostream>

//用内存池实现队列
template<typename T>
class Queue;
const int QueueItem_Count = 10;
//内存池
template<typename T>
class QueueItem
{
public:
	QueueItem(T val = T())
		:mdata(val),pnext(NULL)
	{}
	void* operator new(size_t size)
	{
		if(pool == NULL)
		{
			pool = (QueueItem<T>*)new char[size*QueueItem_Count];
			QueueItem<T>* pCur = pool;
			for(pCur;pCur < pool + QueueItem_Count -1;pCur = pCur + 1)
			{
				pCur->pnext = pCur + 1;
			}
			pCur->pnext = NULL;
		}
		void *ptr = pool;
		pool = pool->pnext;
		return ptr;
	}

	void operator delete(void *ptr)
	{
		QueueItem<T>* pqptr = (QueueItem<T>*)ptr;
		pqptr->pnext = pool;
		pool = pqptr;
	}
private:
	template<typename T>
	friend class Queue;
	T mdata;
	QueueItem<T> *pnext;
	static QueueItem<T>* pool;
};

template<typename T>
QueueItem<T>* QueueItem<T>::pool = NULL;

#pragma warning(disable:4996);

template<typename T>
class Queue
{
public:
	Queue()
	{
		ptail = phead = new QueueItem<T>();
	}

	~Queue()
	{
		QueueItem<T>* pCur = phead;
		QueueItem<T>* pNext;
		while(pCur != NULL)
		{
			pNext = pCur->pnext;
			delete pCur;
			pCur = pNext;
		}
		phead = NULL;
	}

	void push(T val)
	{
		QueueItem<T>* pnewitem = new QueueItem<T>(val);
		ptail->pnext = pnewitem;
		ptail = ptail->pnext;
	}

	bool Empty()
	{
		return (phead == ptail) && (phead != NULL);
	}

	void pop()
	{
		if(Empty())
		{
			throw std::exception("Queue is empty!");
		}
		QueueItem<T>* pCur = phead->pnext;
		phead->pnext = pCur->pnext;
		delete pCur;
	}

	T back()
	{
		if(Empty())
		{
			throw std::exception("Queue is empty!");
		}
		return ptail->mdata;
	}

	T front()
	{
		if(Empty())
		{
			throw std::exception("Queue is empty!");
		}
		return phead->pnext->mdata;
	}
private:
	QueueItem<T> *phead;
	QueueItem<T> *ptail;
};

int main()
{
	Queue<int> que;
	for(int i = 0;i < 5;++i)
	{
		que.push(i+1);
	}
	que.pop();
	auto front = que.front();
	auto back = que.back();
	std::cout << front << std::endl;
	std::cout << back << std::endl;
	return 0;
}

此设计内存池通用性不高,只能设计队列。
下面是通用内存池的设计:

//通用的内存池
const int MEM_SIZE = 10;
template<typename T>
class MEM_POOL
{
public:
	MEM_POOL()
	{
		pool = NULL;
	}
	
	void* Alloc(rsize_t size)
	{
		if(NULL == pool)
		{
			pool = (Node*)new char[(size+4)*MEM_SIZE]();
			Node* pCur = pool;
			for(pCur;pCur < pool + MEM_SIZE -1;pCur = pCur + 1)
			{
				pCur->next = pCur + 1;
			}
			pCur->next = NULL;
		}
		void* rt = pool;
		pool = pool->next;
		return rt;
	}

	void Dealloc(void* ptr)
	{
		Node* pptr = (Node*)ptr;
		if(NULL == pptr)
		{
			return;
		}
		pptr->next = pool;
		pool = pptr;
	}
private:
	class Node
	{
	public:
		Node(T data):mdata(data),next(NULL){}
	public:
		T mdata;
		Node* next;
	};
	Node* pool;
};

class Student
{
public:
	Student(std::string name,std::string id,int age)
		:mname(name),mid(id),mage(age)
	{}

	void* operator new(size_t size)
	{
		return mm.Alloc(size);
	}
	void operator delete(void* ptr)
	{
		mm.Dealloc(ptr);
	}
private:
	std::string mname;
	std::string mid;
	int mage;
	static MEM_POOL<Student> mm;
};

MEM_POOL<Student> Student::mm;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值