内存池

什么是内存池?????

通常我们用new或malloc来分配内存的话,由于申请的大小不确定,所以当频繁的使用时会造成内存碎片和效率的降低。为了克服这种问题我们提出了内存池的概念。内存池是一种内存分配方式。内存池的优点就是可以有效的减少内存碎片化,分配内存更快速,减少内存泄漏等优点。
内存池是在真正使用内存之前,先申请分配一个大的内存块留作备用。当真正需要使用内存的时候,就从内存池中分配一块内存使用,当使这块用完了之后再还给内存池。若是内存块不够了就向内存再申请一块大的内存块。

可以看出这样做有两个好处:
1、由于向内存申请的内存块都是比较大的,所以能够降低外碎片问题。
2、一次性向内存申请一块大的内存慢慢使用,避免了频繁的向内存请求内存操作,提高内存分配的效率。

内存碎片化:
造成堆利用率很低的一个主要原因就是内存碎片化。如果有未使用的存储器,但是这块存储器不能用来满足分配的请求,这时候就会产生内存碎片化问题。内存碎片化分为内部碎片和外部碎片。

内碎片:
内部碎片是指一个已分配的块比有效载荷大时发生的。(举个栗子:假设以前分配了10个大小的字节,现在只用了5个字节,则剩下的5个字节就会内碎片)。内部碎片的大小就是已经分配的块的大小和他们的有效载荷之差的和。因此内部碎片取决于以前请求内存的模式和分配器实现的模式。

内存池_第1张图片

内存池_第2张图片

内存池的设计主要包含三步:
1、初始化
在创建内存池的时候为内存池分配了一块很大的内存,便于以后的使用。
2、分配内存
当需要内存的时候就去内存池里面分配内存。
3、回收内存
当从内存池里面分配来的内存使用完毕之后,需要将这块内存还给内存池。

#pragma once  
#include  
using namespace std;  
//用链表来实现内存池,每一个结点都挂有一块内存  
template  
class ObjectPool  
{  
       struct BlockNode         //每一个结点类型  
       {  
              void* _memory;        //指向一块已经分配的内存  
              BlockNode * _next;    //指向下一个结点  
              size_t _objNum;       //记录这块内存中对象的个数  
              BlockNode(size_t objNum)  
                     :_objNum(objNum)  
                     , _next(NULL)  
              {  
                     _memory = malloc(_objNum*_itemSize);  
              }  
              ~BlockNode()  
              {  
                     free(_memory);  
                     _memory = NULL;  
                     _next = NULL;  
                     _objNum = 0;  
              }  
       };  
protected:  
       size_t _countIn;      //当前结点的在用的计数  
       BlockNode* _frist;    //指向链表的头  
       BlockNode* _last;     //指向链表的尾  
       size_t _maxNum;        //记录内存块最大的容量  
       static size_t _itemSize;   //单个对象的大小  
       T* _lastDelete;        //指向最新释放的那个对象的空间  
public:  
       ObjectPool(size_t initNum = 32, size_t maxNum = 100000)  //默认最开始内存块有32个对象,一个内存块最大有maxNum个对象  
              :_countIn(0)  
              , _maxNum(maxNum)  
              , _lastDelete(NULL)  
       {  
              _frist = _last =new BlockNode(initNum);   //先开辟一个结点,这个结点里面的内存块能够存放initNum个对象  
       }  
       ~ObjectPool()  
       {  
              Destory();  
       }  
       T* New()                   //分配内存  
       {  
              if (_lastDelete)         //先到释放已经用完并且换回来的内存中去找  
              {  
                     T* object = _lastDelete;  
                     _lastDelete = *((T**)_lastDelete);  //将_lastDelete转换成T**,*引用再取出来T*,也就是取出前T*类型大小的单元  
                     return new(object) T();        //把这块内存用从定位new初始化一下  
              }  
              //判断还有没有已经分配的内存且还未使用,如果没有内存的话就要再分配内存  
              if (_countIn >= _last->_objNum)     //大于等于表示没有了,这时候就要分配内存了  
              {  
                     size_t size =2*_countIn;  
                     if (size > _maxNum)            //块的最大大小不能超过maxNum,如果没超过就以二倍增长  
                           size = _maxNum;  
                     _last->_next = new BlockNode(size);  
                     _last = _last->_next;  
                     _countIn = 0;  
              }  
              //还有已经分配好的未被使用的内存  
              T* object =(T*)((char*)_last->_memory + _countIn*_itemSize);  
              _countIn++;  
              return new(object) T();        //将这块空间用重定位new初始化一下  
       }  
       void Destory()  
       {  
              BlockNode *cur = _frist;  
              while (cur)  
              {  
                     BlockNode* del = cur;  
                     cur = cur->_next;  
                     delete del;            //会自动调用~BlockNode()  
              }  
              _frist = _last = NULL;  
       }  
       void Delete(T* object)          //释放内存  
       {  
              if (object)  
              {  
                     object->~T();         
                     *((T**)object) = _lastDelete;      //将_lastDelete里面保存的地址存到tmp指向空间的前T*大小的空间里面  
                     _lastDelete = object;  
              }  
       }  
protected:  
       static size_t GetItemSize()  
       {  
              if (sizeof(T)>sizeof(T*))  
              {  
                     return sizeof(T);  
              }  
              else  
              {  
                     return sizeof(T*);  
              }  
       }  
};  
template  
size_t ObjectPool::_itemSize =ObjectPool::GetItemSize();          //类外初始化静态变量_itemSize  

你可能感兴趣的:(小游戏&项目)