转:C++内存池
#ifndef _MEMPOOL_H_
#define _MEMPOOL_H_
/*
本类封装了一个内存池,采用模板类,
模板参数就是内存池中分配的对象类型
本类主要用链表来实现,适用于固定大小的内存块分配
*/
#include <vector>
using std::vector;
template<typename T>
class CMemPool
{
struct _MemNode
{
_MemNode *pPrev;
char data[sizeof(T) - sizeof(_MemNode*)];
};
struct _MemBlock
{
_MemBlock *pPrev;
_MemNode *pNode;
};
_MemBlock *m_pBlockHeader; //大内存块链表头指针
_MemNode *m_FreeNodeHeader; //空闲的小块头指针
int m_BlockSize; //当前小内存块数量
private:
void AllocBlocks(); //分配内存块
void ReallocBlocks(); //扩大内存池大小
public:
//构造函数,nInitSize为初始内存块数
CMemPool(int nInitSize = 128) : m_BlockSize(nInitSize), m_pBlockHeader(NULL),m_FreeNodeHeader(NULL)
{
AllocBlocks();
}
//析构函数,释放所有底层内存块
~CMemPool()
{
while(m_pBlockHeader != NULL)
{
_MemBlock *tmp = m_pBlockHeader;
m_pBlockHeader = tmp->pPrev;
free(tmp->pNode);
free(tmp);
}
}
/ * 下面两个函数是主要的对外接口 */
void *AllocBlock(size_t size); //从内存池请求内存,size为分配的内存块大小
void FreeBlock(void *pobj , size_t size ); //把内存归还给内存池,pobj是内存块指针,size为内存块大小
//打印信息,用于调试程序
/* void PrintTestInfo()
{
printf("Handle pool: size = %d, free_index = %d, capacity = %d ", m_BlockSize,m_FreeIndex, m_Blocks.capacity());
}
*/
};
template<typename T>
void *CMemPool<T>::AllocBlock(size_t size)
{
if (size != sizeof(T)) //假如size不等于T类型大小,则使用全局分配符分配内存
{
return malloc(size);
}
if (m_FreeNodeHeader == NULL) //当前没有空闲的内存块,则扩大内存
{
ReallocBlocks();
}
void *p = m_FreeNodeHeader; //从空闲块中分配一块内存
m_FreeNodeHeader = m_FreeNodeHeader->pPrev;
return p;
}
template<typename T>
void CMemPool<T>::FreeBlock(void *pobj, size_t size)
{
if( pobj == NULL ) //pobj不能为NULL
return ;
if( size != sizeof(T) ) //假如size不等于T类型大小,则使用全局释放内存操作符释放内存
{
free(pobj);
}
else //将内存归还给内存池
{
_MemNode *p = (_MemNode*)pobj;
p->pPrev = m_FreeNodeHeader;
m_FreeNodeHeader = p;
}
}
template<typename T>
void CMemPool<T>::AllocBlocks()
{
//分配m_BlockSize大小个内存块,放入内存池
_MemBlock *newBlock = (_MemBlock*)malloc(sizeof(_MemBlock));
//分配大块内存
newBlock->pNode = (_MemNode*)malloc(sizeof(_MemNode) *m_BlockSize);
//将分配的大块内存分成小块,串接在空闲块链表上
newBlock->pNode->pPrev = NULL;
for(int i = 1; i < m_BlockSize; ++i)
{
newBlock->pNode[i].pPrev = &(newBlock->pNode[i - 1]);
}
m_FreeNodeHeader = &newBlock->pNode[m_BlockSize - 1];
newBlock->pPrev = m_pBlockHeader;
m_pBlockHeader = newBlock;
}
template<typename T>
void CMemPool<T>::ReallocBlocks()
{
//将内存池扩大2倍
m_BlockSize *= 2;
AllocBlocks();
}
#endif
//--------------------------------------------------------------------------------
本内存池只适合固定大小的内存块分配,避免频繁分配小块内存造成的内存碎片,同时也提高了分配内存的速度。特别适合服务器程序使用。下面有一个测试程序:
#include "MF_mempool.h"
#include "windows.h"
class Test
{
int ss;
char *p;
static CMemPool<Test> mp;
public:
static void *operator new(size_t size);
static void operator delete(void *pobj, size_t size);
};
CMemPool<Test> Test::mp(512);
void *Test::operator new(size_t size)
{
return mp.AllocBlock(size);
}
void Test::operator delete(void *pobj, size_t size)
{
mp.FreeBlock(pobj, size);
}
#define Max_Blocks 1000000
int _tmain(int argc, _TCHAR *argv[])
{
Test* *ptrarry= new Test *[Max_Blocks];
DWORD ss = GetTickCount();
for(int i = 0; i < Max_Blocks; ++i)
{
ptrarry[i] = new Test;
}
for(int j = Max_Blocks - 1; j >= Max_Blocks; --j)
{
delete ptrarry[j];
}
DWORD end = GetTickCount();
printf("take out time is %d\n", end - ss);
return 0;
}