#include<iostream>
#include<vector>
using namespace std;
#define USHORT int
#define ULONG long
#define MEMPOOL_ALIGNMENT 4
struct CMemBlock
{
public:
int nSize;
int nfree;
USHORT nfirst;
CMemBlock* pnext;
char aData[1];
CMemBlock(USHORT m_InitSize, USHORT nUnitSize);
~CMemBlock();
static void* operator new(size_t, USHORT m_InitSize, USHORT nUnitSize)
{
return ::operator new(sizeof(CMemBlock) + m_InitSize * nUnitSize);
}
};
CMemBlock::CMemBlock(USHORT m_InitSize, USHORT nUnitSize)
:nSize(m_InitSize * nUnitSize),
nfree(m_InitSize-1),
nfirst(1),
pnext(0)
{
char * pData = aData;
for (USHORT i = 1; i < m_InitSize; i++)
{
*reinterpret_cast<USHORT*>(pData) = i;
pData += nUnitSize;
}
}
//memorypool
class CMemPool
{
private:
int m_UnitSize;
int m_InitSize;
CMemBlock* pBlock;
public:
CMemPool();
~CMemPool(){}
void* get();
void free(void *p);
void setUnitSize(int UnitSize){m_UnitSize = UnitSize;}
int getUnitSize(){return m_UnitSize;}
void setInitSize(int InitSize){m_InitSize = InitSize;}
int getInitSize(){return m_InitSize;}
};
CMemPool::CMemPool()
{
m_UnitSize = 4;
m_InitSize = 100;
pBlock = NULL;
if(m_UnitSize>4)
{
m_UnitSize = (m_UnitSize + MEMPOOL_ALIGNMENT-1)&~(MEMPOOL_ALIGNMENT-1);
}
else if(m_UnitSize<=2)
m_UnitSize = 2;
else
m_UnitSize =4;
}
void* CMemPool::get()
{
if(!pBlock)
{
pBlock = new (m_InitSize,m_UnitSize) CMemBlock(m_InitSize,m_UnitSize);
cout<<"chuangjian chenggong~~~~~~~"<<endl;
return (void *)pBlock->aData;
}
CMemBlock* p1 = pBlock;
while(p1&&!p1->nfree)
p1 = p1->pnext;
if(p1)
{
char* pfree = p1->aData+(p1->nfirst*m_UnitSize);
p1->nfirst = *((USHORT *)pfree);
p1->nfree--;
return (void *)pfree;
}
else
cout<<"~~~~~enough~~~~~~~~";
}
void CMemPool::free(void *p)
{
CMemBlock* p2 = pBlock;
while((((ULONG)p2->aData>(ULONG)p)||(ULONG)p>((ULONG)p2->aData+p2->nSize))&&p2)
{
p2 = p2->pnext;
}
if(p2)
{
p2->nfree++;
*((USHORT*)p) = p2->nfirst;
p2->nfirst = (USHORT)(((ULONG)p-(ULONG)p2->aData)/m_UnitSize);
}
}
int main()
{
ULONG * p;
CMemPool pool;
int i;
for(i=0;i<101;i++)
{
p=(ULONG *)pool.get();
cout<<*p<<endl;
}
return 0;
}
注:CMemBlock中注意new的用法。n
ew
和
delete
操作符我们应该都用过,它们是对堆中的内存进行申请和释放,而这两个都是不能被重载的。要实现不同的内存分配行为,需要重载
operator new
,而不是
new
和
delete
。
placement new是operator new的一个重载版本,只是我们很少用到它。如果你想在已经分配的内存中创建一个对象,使用new是不行的。也就是说placement new允许你在一个已经分配好的内存中(栈或堆中)构造一个新的对象。原型中void*p实际上就是指向一个已经分配好的内存缓冲区的的首地址。
我们知道使用new操作符分配内存需要在堆中查找足够大的剩余空间,这个操作速度是很慢的,而且有可能出现无法分配内存的异常(空间不够)。placement new就可以解决这个问题。我们构造对象都是在一个预先准备好了的内存缓冲区中进行,不需要查找内存,内存分配的时间是常数;而且不会出现在程序运行中途出现内存不足的异常。所以,placement new非常适合那些对时间要求比较高,长时间运行不希望被打断的应用程序。