C++:对象池的实现

对象池的实现

对象池:在一部分内存空间(池子)中事先实例化好固定数量的对象,当需要使用池中的对象时,首先判断该池中是否有闲置(暂未使用)的对象,如果有,则取出使用,如果没有,则在池中创建该对象。当一个对象不再被使用时,其应该将其放回对象池,以便后来的程序使用。

我们来看实例了解一下为什么需要对象池呢?
我们先来看一下这样一个例子:

//Author:Mr.Rain
#include <iostream>
using namespace std;


template <typename T>
class Queue
{
public:
	Queue()
	{
		_front = _rear = new QueueItem();
	}
	~Queue()
	{
		QueueItem *cur = _front;
		while (cur != nullptr)
		{
			_front = _front->_next;
			delete cur;
			cur = _front;
		}
	}
	void push(const T &val)//入队
	{
		QueueItem *item = new QueueItem(val);
		_rear->_next = item;
		_rear = item;
	}
	void pop()//出队
	{
		if (empty()) return;
		QueueItem *first = _front->_next;
		_front->_next = first->_next;
		if (_front->_next == nullptr)
		{
			_rear = _front;
		}
		delete first;
	}
	T front()const
	{
		return _front->_next->_data;
	}
	bool empty()const
	{
		return _front == _rear;
	}
private:
	struct QueueItem
	{
		QueueItem(T data = T()):_data(data), _next(nullptr){}
		T _data;
		QueueItem *_next;
	};

	QueueItem *_front;//队头
	QueueItem *_rear;//队尾
};


int main()
{
	Queue<int> que;
	for (int i=0; i<1000000; ++i)
	{
		que.push(i);
		que.pop();
	}
	cout << que.empty() << endl;

	return 0;
}

这里我们实现了一个队列并执行成功,入队一个出队一个,最后队列为空。
在这里插入图片描述
       但是我们每次push都会执行一次new QueueItem,每次pop都会执行一次QueueItem的delete;对于我们结点QueueItem来说,将其内存释放掉,下一次push时又需要一个新的QueueItem结点,与原来不同的是只是结点中数据不同,短时间内大量对其进行调用,完全没有必要,会影响我们程序的性能。
       因此我们产生一个QueueItem的对象池,在对象池中生成100000QueueItem结点的对象池,需要一个QueueItem直接从对象池中拿,delete时将结点内存归还到内存池中,短时间对QueueItem开辟释放开辟释放性能会有很大提升。

此时我们利用new与delete针对于QueueItem设计一个对象池:
对象池大致结构如下:
在这里插入图片描述
代码实现:

//Author:Mr.Rain
#include <iostream>
using namespace std;


template <typename T>
class Queue
{
public:
	Queue()
	{
		_front = _rear = new QueueItem();
	}
	~Queue()
	{
		QueueItem *cur = _front;
		while (cur != nullptr)
		{
			_front = _front->_next;
			delete cur;
			cur = _front;
		}
	}
	void push(const T &val)//入队
	{
		QueueItem *item = new QueueItem(val);
		_rear->_next = item;
		_rear = item;
	}
	void pop()//出队
	{
		if (empty()) return;
		QueueItem *first = _front->_next;
		_front->_next = first->_next;
		if (_front->_next == nullptr)
		{
			_rear = _front;
		}
		delete first;
	}
	T front()const
	{
		return _front->_next->_data;
	}
	bool empty()const
	{
		return _front == _rear;
	}
private:
	//产生一个QueueItem的对象池(10000个QueueItem结点)
	struct QueueItem
	{
		QueueItem(T data = T()):_data(data), _next(nullptr){}
		//给QueueItem提供自定义内存管理
		void* operator new(size_t size)
		{
			if (_itemPool == nullptr)
			{
				_itemPool = (QueueItem*)new char[POOL_ITEM_SIZE * sizeof(QueueItem)];
				QueueItem *p = _itemPool;//指向首地址
				for (; p < _itemPool + POOL_ITEM_SIZE; ++p)
				{
					p->_next = p + 1;
				}
				p->_next = nullptr;//最后一个结点地址域nullptr
			}
			QueueItem *p = _itemPool;
			_itemPool = _itemPool->_next;
			return p;
		}
		void operator delete(void *ptr)
		{
			QueueItem *p = (QueueItem*)ptr;//归还结点
			p->_next = _itemPool;
			_itemPool = p;
		}
		T _data;
		QueueItem *_next;
		static QueueItem *_itemPool;//指向对象池的起始地址
		static const int POOL_ITEM_SIZE = 100000;
	};

	QueueItem *_front;//队头
	QueueItem *_rear;//队尾
};

template <typename T>
typename Queue<T>::QueueItem *Queue<T>::QueueItem::_itemPool = nullptr;

int main()
{
	Queue<int> que;
	for (int i=0; i<1000000; ++i)
	{
		que.push(i);
		que.pop();
	}
	cout << que.empty() << endl;

	return 0;
}

测试一下:测试成功。
       由于对象池的实现,提前开辟好了内存池的空间,用的时候直接取,不用的时候直接归还,大大提高了使用的效率。
在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值