内存池设计(五)

 将以上代码组装,并自己设计累 user 来测试这个内存池

#include<iostream>
#define MEMPOOL_ALIGNMENT 8  // 对齐长度
using namespace std;
///内存块及其信息表 memory block-----------------------
template<typename T>
struct memoryblock
{
    int nsize;//该内存块的大小
    int nfree;// 该内存还有多少可分配单位
    int nfirst;//当前可分配的第一个单位序号
    memoryblock *pnext;// 指向下一个内存块
    char adata[1];// 用于标记分配单元开始的位置
    memoryblock(int nunitsize,int nunitamount):nsize(nunitsize * nunitamount),nfree(nunitamount-1),nfirst(1),pnext(NULL)
    // nunitsize 存储单位的大小 即 sizeof(T) nunitamount 内存块规模
    // nfree 空闲存储单位为 nunitamount-1 nfirst 初值为1 pnext指向下一个内存块的指针为NULL
    {
        //为空闲区编号
      char *ppdata=adata;
      cout<<"存储区首指针 ppdate ="<<(int*)ppdata<<endl;
      for(int i=1;i<nunitamount;i++)
      {
          //当前存储单位存储下一个可分配单位的序号
          (*(unsigned short *)ppdata)=i;
          cout<<"下一个可分配单位序号: "<<(int)*ppdata<<endl;
          //移动指针使之指向下一个单位
          ppdata+=nunitsize;
      }
      cout<<"-------------调用内存块的构造函数-------------------"<<endl;
    }
      void *operator new(size_t,int nunitsize,int nunitamount)
      {
          cout<<"分配内存并创建memoryblock 对象"<<endl;
          return ::operator new(sizeof(memoryblock)+nunitsize*nunitamount);
      }
      void operator delete(void *pblock)
      {
          ::operator delete(pblock);
          cout<<"---------------调用内存块的析构函数----------------"<<endl;
      }
};
///内存池信息表
template<typename T>
struct memorypool
{
    int ninitsize;///首块长度
    int ngrowsize;///后续块长度
    int nunitsize;/// 定义存储单位大小
    memoryblock<T>*pblock;
memorypool(int _ngrowsize=10,int _ninitsize=3)
{
    cout<<"-----------------调用内存池的构造函数---------------"<<endl;
    ninitsize=_ninitsize;
    ngrowsize=_ngrowsize;
    pblock=NULL;
    nunitsize=sizeof(T);
    if(sizeof(T)>4)///调整存储单位的大小
        nunitsize=(sizeof(T)+(MEMPOOL_ALIGNMENT-1)) & ~(MEMPOOL_ALIGNMENT-1);// 返回值为8的倍数 所谓的内存对齐
    else if(sizeof(T)<2)
        nunitsize=2;
    else
        nunitsize=4;
}
~memorypool()
{
    memoryblock<T>*pmyblock=pblock;
    while(pmyblock!=NULL)
    {
        pmyblock=pmyblock->pnext;
        delete(pmyblock);
    }
    cout<<"--------------------调用内存池的析构函数-------------------"<<endl;
}
///用于向内存池请求存储单位的函数,也是内存池向用户提供的主要服务
///遍历内存块链表,找到nfree 大于0 即有空闲的内存块 并从其上分配存储单位
///然后将memoryblock 中nfree 减一 并修改空闲存储单位链表头指针 nfirst 的值
void *allocate(size_t num)
{
    for(int i=0;i<num;++i)
    {
    if(NULL==pblock)
    {
        ///创建首内存块
        pblock=(memoryblock<T>*)new (nunitsize,ninitsize)
        memoryblock<T>(nunitsize,ninitsize);
        return (void*)pblock->adata;///返回内存块中数据元素存储区指针
    }
    ///为内存寻找符合条件的内存块
    memoryblock<T>*pmyblock=pblock;
    while(pmyblock!=NULL&&0==pmyblock->nfree)
        pmyblock=pmyblock->pnext;
    if(pmyblock!=NULL)
    {
        cout<<"找到内存空间 first= "<<pmyblock->nfirst<<endl;
        ///找到后进行内存分配
        char *pfree=pmyblock->adata+pmyblock->nfirst*nunitsize;
        pmyblock->nfirst=*((unsigned short*)pfree);
        pmyblock->nfree--;
        ///返回找到的存储单位指针
        return (void*)pfree;
    }
    else
    {
        ///没有找到 说明当前内存块已用完
        if(0==ngrowsize)return NULL;
        cout<<" 否则分配新内存块"<<endl;
        //分配一个后续内存块
        pmyblock=(memoryblock<T>*)new(nunitsize,ngrowsize)
        memoryblock<T>(nunitsize,ngrowsize);
        if(NULL==pmyblock)
            return NULL;///失败
        pmyblock->pnext=pblock;
        pblock=pmyblock;
        //返回新内存的的存储区指针
        return (void*)pmyblock->adata;
    }
}
}
//free 函数用于释放内存块 该函数根据pfree 的值找到他所在的内存块 然后将它的序号作为nfirst的值(因为他绝对空闲)
//在pfree 的头两个字节内写入原来nfirst 的值。然后要判断 该block 是否全部为free 方法是检测nfree*nunitsize==size
// 若是 则向系统释放内存 若不是 则将该block 放到链表的头部 因为该block上一定含有内存单元 这样可以减少分配是遍历
//链表所消耗的时间
void free(void *pfree)
{
    //找到p所在的块
    cout<<"释放存储单位内存空间"<<endl;
    memoryblock<T>*pmyblock=pblock;
    memoryblock<T>*preblock=NULL;
    while(pmyblock!=NULL&&(pblock->adata>pfree||pmyblock->adata+pmyblock->nsize))
    {
        preblock=pmyblock;
        pmyblock=pmyblock->pnext;
    }
    //该内存块在被内存池pmyblock 所指向的内存块中
    if(NULL!=pmyblock)
    {
        //1 修改数组链表
        *((unsigned short*)pfree)=pmyblock->nfirst;
        pmyblock->nfirst=(unsigned short)((unsigned long)pfree-(unsigned long)pmyblock->adata)/nunitsize;
        pmyblock->nfree++;
        // 2 判断是否需要向系统释放内存
        if(pmyblock->nsize==pmyblock->nfree*nunitsize)
        {
            //在链表中删除
            delete(pmyblock);
        }
        else
        {
            //将该block 插入队首
            preblock=pmyblock->pnext;
            pmyblock->pnext=pblock;
            pblock=pmyblock;
        }
    }
}
};
class user
{
    int s;
    double s1;
    double s3;
public:
    user(int x):s(x)
    {
        cout<<"-------------------调用 user 的析构函数----------------"<<endl;
    }
    int get()
    {
        return s;
    }
    ~user()
    {
        cout<<"------------------调用user 的析构函数------------------"<<endl;
    }
};
int main()
{
    memorypool<user>m_pool;
    user*dp1=(user*)m_pool.allocate(1);
    cout<<"dp1= "<<dp1<<endl;
    new(dp1)user(1111);
    cout<<" 对象中的数据值为 "<<dp1->get()<<endl;
    user*dp2=(user*)m_pool.allocate(1);
    cout<<"dp2= "<<dp2<<endl;
    new(dp2)user(2222);
    cout<<"对象中的数据值为 "<<dp2->get()<<endl;
     user*dp3=(user*)m_pool.allocate(1);
    cout<<"dp3= "<<dp3<<endl;
    new(dp3)user(3333);
    cout<<"对象中的数据值为 "<<dp3->get()<<endl;
     user*dp4=(user*)m_pool.allocate(1);
    cout<<"dp4= "<<dp4<<endl;
    new(dp4)user(4444);
    cout<<"对象中的数据值为 "<<dp4->get()<<endl;
     user*dp5=(user*)m_pool.allocate(1);
    cout<<"dp5= "<<dp5<<endl;
    new(dp5)user(5555);
    cout<<"对象中的数据值为 "<<dp5->get()<<endl;
     user*dp6=(user*)m_pool.allocate(1);
    cout<<"dp6= "<<dp6<<endl;
    new(dp6)user(6666);
    cout<<" 对象中的数据值为 "<<dp6->get()<<endl;

     user*dp7=(user*)m_pool.allocate(1);
   cout<<"dp7= "<<dp7<<endl;
    new(dp7)user(7777);
    cout<<" 对象中的数据值为 "<<dp7->get()<<endl;

    user*dp8=(user*)m_pool.allocate(1);
   cout<<"dp8= "<<dp8<<endl;
    new(dp8)user(8888);
    cout<<" 对象中的数据值为 "<<dp8->get()<<endl;

     user*dp9=(user*)m_pool.allocate(1);
    cout<<"dp9= "<<dp9<<endl;
    new(dp9)user(9999);
    cout<<" 对象中的数据值为 "<<dp9->get()<<endl;

     user*dp10=(user*)m_pool.allocate(1);
    cout<<"dp10= "<<dp10<<endl;
    new(dp10)user(11111);
    cout<<" 对象中的数据值为 "<<dp10->get()<<endl;

     user*dp11=(user*)m_pool.allocate(1);
    cout<<"dp11= "<<dp11<<endl;
    new(dp11)user(22222);
    cout<<" 对象中的数据值为 "<<dp11->get()<<endl;

     user*dp12=(user*)m_pool.allocate(1);
    cout<<"dp12= "<<dp12<<endl;
    new(dp12)user(33333);
    cout<<" 对象中的数据值为 "<<dp12->get()<<endl;

     user*dp13=(user*)m_pool.allocate(1);
    cout<<"dp13= "<<dp13<<endl;
    new(dp13)user(44444);
    cout<<" 对象中的数据值为 "<<dp13->get()<<endl;

     user*dp14=(user*)m_pool.allocate(1);
    cout<<"dp14= "<<dp14<<endl;
    new(dp14)user(55555);
    cout<<" 对象中的数据值为 "<<dp14->get()<<endl;

     user*dp15=(user*)m_pool.allocate(1);
    cout<<"dp15= "<<dp15<<endl;
    new(dp15)user(66666);
    cout<<" 对象中的数据值为 "<<dp15->get()<<endl;
    return 0;
}

至此 ,内存池的设计以及实现完成。

原文地址:https://www.cnblogs.com/guoyu1024/p/9607079.html