简易内存池(对象池)的实现

#pragma once

#include <vector>
#include <time.h>
#include <string>

// 对象池的实现 针对于一个知道类型的对象
//我们通过对象池 来比较普通向内存中申请空间
//和我们直接向我们的内存池中申请空间的性能对比
template <class T, size_t initNum = 10000> //设定内存池中取出的最大数量为100
class ObjectPool
{
public:
	ObjectPool()
	{
		//这一步的原因是如果对象是char类型的,只有一个字节,那么它里面就不能有4个字节存指向下一个
		//节点的指针了。因为char是一个字节,所以sizeof(T)要和sizeof(T*)比较一下,存取大的。
		//如果是对象T是char类型的,sizeof(char)<sizeof(char*),所以先给char对象开辟四个字节,
		//就可以存_freeList链表中下一个节点的地址了。尽管是char是一个字节的,存进去之后只占
		//最低的一个字节8位
		_itemSize = sizeof(T) < sizeof(T*) ? sizeof(T*) : sizeof(T);
		//给_freeList开辟这么大的空间进行维护,initNum*_itemSize:节点数*每个对象的字节数
		_start = (T*)malloc(initNum*_itemSize);
		_end = _start + initNum;
		_freeList = nullptr;  //给链表初始化为空
	}

	T*& Nex_Obj(T* obj)
	{
		//强转出T**在解引用肯定是T*,在32位和64位都可以表示对象的大小,
		//解决了平台不统一的问题,适应32位和64位机器
		// 比如对象是int , int**在解引用是int*, 在32位下是4,在64位下是8.都可以平台统一

		//强转成(T**)在解引用后, 就是寻求下一个位置,到达_freeList的下一个位置
		return  *(T**)obj; 
	
	}
	T* New()
	{
		//1.如果freeList有对象,优先到freeList链表中获取 空间
		//2.要是freeList中没有对象,再到内存池中去取
		T* obj = nullptr;
		if (_freeList != nullptr)
		{
			obj = _freeList;
			_freeList = Nex_Obj(obj);
		}
		else
		{
			if (_start == _end) // 如果内存池中没有数据
			{
				_start = (T*)malloc(initNum *_itemSize);//再开initNum个空间
				_end = _start + initNum; //end指向末尾
			}
			// 空间足够 从内存池中取数据
			obj = _start;  //_start 是char* ,得强转成T*,才可以给T*类型的变量赋值
			//obj就是从内存池中取出的一段地址
			_start += 1; //向后移动一个节点的itemSize;
		}
		//new的 定位表达式
		new(obj)T; //创建一个对象 但是不开辟空间, 而是用在自己的空间obj上,
		//new的定位 表达式。
		//创建对象但是并不分配内存,而是在已有的内存块上面创建对象。
		//用于需要反复 创建并删除的对象上,可以降低分配释放内存的性能
		//消耗
		// obj这个位置必须是指针,在这里obj已经指向了分配好的内存.
		// 
		return obj;
	}
	void Delete(T* ptr)
	{
		ptr->~T(); //先调用析构函数清理空间上的资源

		Nex_Obj(ptr) = _freeList; //释放链表 将空间归还给_freeList, 头插归还
		_freeList = ptr;
	}

private:
	T* _start;     //管理内存池的首指针
	T* _end;       //管理内存池的尾指针
	size_t _itemSize; 

	T* _freeList;     //链表指针
};

//void TestObjectPool()
//{
//	ObjectPool<int> pool;
//	int *p1 = pool.New();
//	int *p2 = pool.New();
//	int *p3 = pool.New();
//
//	pool.Delete(p1);
//	pool.Delete(p2);
//	pool.Delete(p3);
//
//	cout << p1 << endl;
//	cout << p2 << endl;
//	cout << p3 << endl;
//
//	int *p4 = pool.New();
//	int *p5 = pool.New();
//	int *p6 = pool.New();
//
//	pool.Delete(p4);
//	pool.Delete(p5);
//	pool.Delete(p6);
//
//	cout << p4 << endl;
//	cout << p5 << endl;
//	cout << p6 << endl;
//}


void BenchMark()                //性能分析
{
	size_t n = 1000000;
	
	vector<string*>v1;
	v1.reserve(n);
	size_t begin1 = clock();
	for (size_t i = 0; i < n; i++)
	{
		v1.push_back(new string);
	}
	for (size_t i = 0; i < n; i++)
	{
		delete v1[i];
	}
	size_t end1 = clock();
	v1.clear();
	cout << "直接系统申请内存:" << end1 - begin1 << endl;


	vector<string*>v2;
	v2.reserve(n);
	ObjectPool<string> pool;
	size_t begin2 = clock();

	for (size_t i = 0; i < n; i++)
	{
		v2.push_back(pool.New());
	}
	for (size_t i = 0; i < n; i++)
	{
		pool.Delete(v2[i]);
	}
	size_t end2 = clock();

	v2.clear();

	cout << "Pool 申请内存: " << end2 - begin2 << endl;
}

发布了55 篇原创文章 · 获赞 12 · 访问量 5259

猜你喜欢

转载自blog.csdn.net/weixin_43939593/article/details/103353259
今日推荐