将以上代码组装,并自己设计累 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; }
至此 ,内存池的设计以及实现完成。