首先引入指针的概念,指针是用来记录地址,并对所指向的地址上所指向类型的数据进行修改。
地址非常关键,将地址转换为指针类型,用指针引用指向该地址的所指向类型的数据。
然后我说说内存池的好处吧。用这种技术的好处有两: 一. 节省空间, 普通的new操作由于需要记住申请的大小, 一般需要更多的空间. 而应用这种技术则不需要额外的空间. 二. 操作速度快, 此种的new和delete操作只是对链表的添加和删除操作, 不需要做真正的系统空间分配, 速度更快.
然后我说说我实现内存池的想法:分配一大块内存能存放215个T类型的对象,然后每个小内存块的前四字节的内容填充为下一个小内存块的地址,(最后一个小内存块的前四字节的内容是0)形成自由空闲链表.如果需要分配内存的话,将第一块小内存返回给operator new调用者,然后空闲链表的头结点的指针 就为下一个小内存块的地址。以此类推。
如果需要回收内存的话,将这块内存的前四字节的内容填充为空闲链表的头结点的地址,然后将空闲填表的头结点的指针指向这块内存。
然后我把pool类的实现代码贴出来:
class pool
{
public:
pool(size_t size); //为大小为n的对象创建一个分配器
void* alloc(size_t n); //为一个对象分配足够内存
void free(void* p,size_t n); //将p所指的内存回收到内存池中
~pool(); //释放内存池中全部内存
private:
char* newblock; //大内存块的首地址
char* headoffreelist; //自由空闲链表的头结点指针
static const int block_size; //小内存块的数量
};
const int pool::block_size=215;
pool::pool(size_t size)
{
newblock=(char*)(::operator new(block_size*size));
for(int i=0; i!=block_size-1;++i)
{
*(char**)(newblock+i*size)=newblock+(i+1)*size;
}
*(char**)(newblock+(block_size-1)*size)=NULL;
headoffreelist=newblock;
}
void* pool::alloc(size_t n)
{
char* p=headoffreelist;
headoffreelist=*(char**)p;
return p;
}
void pool::free(void* p,size_t n)
{
if(p ==NULL)return;
char* pRecycleMem=(char*)p;
*(char**)pRecycleMem=headoffreelist;
headoffreelist=pRecycleMem;
}
pool::~pool()
{
::operator delete(newblock);
}
最后我说下如何使用pool类给其他类添加特制的内存管理方式:
class airplane
{
public:
static void * operator new(size_t size);
static void operator delete(void *p, size_t size);
private:
airplane *rep; // 指向实际描述的指针
static pool mempool; // airplanes的内存池
};
// 为airplane对象创建一个内存池,
// 在类的实现文件里实现
pool airplane::mempool(sizeof(airplane));
inline void * airplane::operator new(size_t size)
{
if(size!=sizeof(airplane))
return ::operator new(size);
return mempool.alloc(size);
}
inline void airplane::operator delete(void *p,
size_t size)
{
if(size !=sizeof(airplane))
::operator delete(p);
else
mempool.free(p, size);
}