【C++重载new和delete运算符实现一个对象池】

使用对象池的原因

 

类似于SGI的二级空间配置器,但是对象池的实现比二级空间配置器实现的原理简单了很多。想了解二级空间配置器可以查看博主的另外一篇文章https://blog.csdn.net/qq_42418668/article/details/94740594

 

当我们需要,多次使用newdelete操作向系统申请和释放堆空间会使得我们的程序进程的开销变得非常的大而且效率也非常低。

所以我们可以通过重载new和delete构建一个对象池,来帮助我们提高自己程序的效率和减少不必要的开销。

实现原理

  1.     分配过程(new)
     

    我们首先申请比如100000块内存空间,用这个块类型的指针指向这个申请好内存的首地址。如图。这个块可以是一个链式队列的一个节点或者一个树的节点等。

    当我们要分配给用户一块空间的时候我们就可以,先将_itemPool的地址保存到临时指针p,然后再_itemPool++的操作,然后再将p返回给用户即可。

  2.    释放过程(delete)
    比如我们现在的内存分配状况如图所示:现在用户需要归还第 1 块内存。

       我们首先要归还块的首地址指向_itemPool的下一个块,然后再将_itemPool指向归还的块的地址。即可

 

使用队列的push和pop入队和出队操作模拟一个简单对象池的实现的例子

#include <iostream>

using namespace std;

/*
运算符的重载  :成员方法、全局方法

内存池 进程池 线程池 连接池 对象池
*/
template<typename T>
class Queue
{
public:
	Queue()
	{
		_front = _rear = new QueueItem();
	}
	~Queue()
	{
		QueueItem *cur = _front;
		while (cur != nullptr)
		{
			_front = cur->_next;
			delete cur;
			cur = _front;
		}
	}
	Queue(const Queue&obj) = delete;
	void operator=(const Queue&obj) = delete;
	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 _rear == _front; }
	struct QueueItem//产生一个QueueItem 的对象池
	{
		QueueItem(T data = T()) :_data(data),_next(nullptr) {}
		void *operator new(size_t size)
		{
			if (_itemPool == nullptr)
			{
				//由于我们不知道QueueItem的具体大小(模板未进行实例化)所以我们这里用char 1字节作为new的基准
				_itemPool = (QueueItem*)new char[POOL_ITEM_SIZE * sizeof(QueueItem)];
				QueueItem *p = _itemPool;
				//把开辟的POOL_ITEM_SIZE个块关联起来
				for (; p != _itemPool + POOL_ITEM_SIZE - 1; ++p)
				{
					p->_next = p + 1;
				}
				//最后一块的next置为空
				p->_next = nullptr;
			}
			//将第一块可以分配的块分配给用户
			QueueItem *p = _itemPool;
			_itemPool = _itemPool->_next;
			return p;
		}
		void operator delete(void *ptr)
		{
			//进行归还操作
			QueueItem *p = (QueueItem*)ptr;
			p->_next = _itemPool;
			_itemPool = p;
		}
		static QueueItem *_itemPool;
		static const int POOL_ITEM_SIZE = 1000000;
		T _data;
		QueueItem *_next;
	};
private:
	QueueItem *_front;//指向头节点
	QueueItem *_rear;//指向队尾
};

//typename 告诉编译器后面是类型
template<typename T>
typename Queue<T>::QueueItem *Queue<T>::QueueItem::_itemPool = nullptr;
int main()
{
	Queue<int> que;
	for (int i = 0; i < 1000000; ++i)//大量的new delete;不划算
	{
		que.push(i);
		que.pop();
	}

	cout << que.empty() << endl;
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值