您的位置:首页 > 编程语言 > C语言/C++

C++实现内存池

2016-11-04 12:39 369 查看
想用C++实现内存池,参考了一下别人的代码

http://blog.csdn.net/chexlong/article/details/7071922

人家对内存块的管理是用vector,动态的插入与删除,来做内存的分配与回收,基于人家的代码,做的一些改动,用Map进行管理,用标志来区分该内存块是否已分配,回收时,内存里面的内容也得重置掉,以免影响下一次的调用。

代码如下

#ifndef _MEM_POOL_H
#define _MEM_POOL_H

#include <vector>
#include <iostream>
#include <map>
#include "string.h"

using namespace std;

/*
在内存池中分配固定大小的内存块

该类的目的是加速内存分配速度,并且减少因重复分配相同
内存时产生的内存碎片,比如在服务器应用程序中。
*/

struct sBlock
{
short   isHasUse; // 是否使用过
int     iIndx;    // 编号
char*   pBlock;   // 内存块所指向的地址
};

class CMemPool
{
public:

//创建大小为blockSize的内存块,内存池数目为预分配的数目preAlloc
CMemPool(std::size_t blockSize, int preAlloc = 0);

~CMemPool();

//获取一个内存块。如果内存池中没有足够的内存块,则会自动分配新的内存块
//如果分配的内存块数目达到了最大值,则会返回一个异常
void* Get();

//释放当前内存块,将其插入内存池
void Release(void* ptr);

//返回内存块大小
std::size_t BlockSize() const;

//返回内存池中内存块数目
int Allocated() const;

//返回内存池中可用的内存块数目
int Available() const;

//得到内存块的数量
int GetBlockNum() const;

private:
CMemPool();
CMemPool(const CMemPool&);
CMemPool& operator = (const CMemPool&);

enum
{
BLOCK_RESERVE = 32
};

typedef std::vector<char*> BlockVec;

std::size_t m_blockSize;
int         m_maxAlloc;
int         m_allocated;
BlockVec    m_blocks;

typedef map<int, sBlock> BlockMap;
BlockMap    m_blocks_map;

};

inline std::size_t CMemPool::BlockSize() const
{
return m_blockSize;
}

// 得到已经分配出去的有多少
inline int CMemPool::Allocated() const
{
int iTotalUseNum = 0;
for (auto it = m_blocks_map.begin(); it != m_blocks_map.end(); ++it)
{
if (it->second.isHasUse == 1)
{
iTotalUseNum += 1;
}
}
return iTotalUseNum;
}

inline int CMemPool::Available() const
{
int iAvailableNum = 0;
for (auto it = m_blocks_map.begin(); it != m_blocks_map.end(); ++it)
{
if (it->second.isHasUse == 0)
{
iAvailableNum += 1;
}
}
return iAvailableNum;
}

inline int CMemPool::GetBlockNum() const
{
return m_blocks_map.size();
}

CMemPool::CMemPool(std::size_t blockSize, int preAlloc) :
m_blockSize(blockSize),
m_allocated(preAlloc)
{
m_blocks_map.clear();
for (int i = 0; i < preAlloc; ++i)
{
sBlock nBlock;
nBlock.isHasUse = 0;
nBlock.iIndx = i;
nBlock.pBlock = new char[m_blockSize];
m_blocks_map[i] = nBlock;
}

}

CMemPool::~CMemPool()
{
for (BlockMap::iterator it = m_blocks_map.begin(); it != m_blocks_map.end(); ++it)
{

cout << " delete the block indx = " << it->second.iIndx << "  " << endl;
delete[] it->second.pBlock; // 删除内存对应的内存空间
}
m_blocks_map.clear();
}

void* CMemPool::Get()
{
// 分配内存地址
for (auto it = m_blocks_map.begin(); it != m_blocks_map.end(); ++it)
{
if (it->second.isHasUse == 0)
{
it->second.isHasUse = 1; // 表示该内存块已经被分配出去了
cout << " this block indx = " << it->second.iIndx << "  has be used " << endl;
return it->second.pBlock;
}
}

// 如果内存map 都被用完啦,那么则得添加新的内存块到map中
auto iter = m_blocks_map.end();
iter--; // 得往后减一个,才能取到最后一个元素

int maxIndx = iter->second.iIndx;

int curIndx = maxIndx + 1;
sBlock nBlock;
nBlock.iIndx = curIndx;
nBlock.isHasUse = 0;
nBlock.pBlock = new char[m_blockSize];
m_blocks_map[curIndx] = nBlock;

// 将新添加的分配出来用
m_blocks_map[curIndx].isHasUse = 1;
cout << " this block indx = " << m_blocks_map[curIndx].iIndx << " create and  has be used " << endl;
return m_blocks_map[curIndx].pBlock;

}

void CMemPool::Release(void* ptr)
{
for (auto it = m_blocks_map.begin(); it != m_blocks_map.end(); ++it)
{
char * pTmp = reinterpret_cast<char*>(ptr);
if (it->second.pBlock == pTmp)
{
cout << " the block indx = " << it->second.iIndx << "   has be Released " << endl;
it->second.isHasUse = 0;
memset(pTmp, 0, m_blockSize);
}
}
}

#endif


测试代码

#include "MemPool.h"

#define DATA_BLOCK_LEN 50

struct  sTest
{
int m_id;
int m_num;
};

struct  sTest2
{
int m_id;
int m_num;
char m_str[10];
};

int main()
{
CMemPool myPool1(DATA_BLOCK_LEN, 20);

cout << "myPool1 block size = " << myPool1.BlockSize() << endl;
cout << "myPool1 allocated block num = " << myPool1.Allocated() << endl;
cout << "myPool1 available block num = " << myPool1.Available() << endl;
cout << "myPool1 total block num = " << myPool1.GetBlockNum() << endl <<endl;

// 分配一个内存块
struct sTest* pTest;
pTest = (struct sTest*)(myPool1.Get());

pTest->m_id = 25;
pTest->m_num = 10000;
cout << pTest->m_id <<"  " <<pTest->m_num << endl;

struct sTest* pTest2;
pTest2 = (struct sTest*)(myPool1.Get());

pTest2->m_id = 123;
pTest2->m_num = 13445;
cout << pTest2->m_id << "  " << pTest2->m_num << endl << endl;

cout << "myPool1 allocated block num = " << myPool1.Allocated() << endl;
cout << "myPool1 available block num = " << myPool1.Available() << endl << endl;

// 回收该内存块
myPool1.Release(pTest);
pTest = NULL;

cout << "myPool1 allocated block num = " << myPool1.Allocated() << endl;
cout << "myPool1 available block num = " << myPool1.Available() << endl << endl;

//pTest = (struct sTest*)(myPool1.Get());
//cout << pTest->m_id << endl;
//cout << pTest->m_num << endl;
struct sTest2* pTtmp;
pTtmp = (struct sTest2*)(myPool1.Get());
pTtmp->m_id = 1234;
char * cTmp= "skskdlsl";
memcpy(pTtmp->m_str, cTmp, strlen(cTmp));
cout << pTtmp->m_str << endl;

cout << "myPool1 allocated block num = " << myPool1.Allocated() << endl;
cout << "myPool1 available block num = " << myPool1.Available() << endl << endl;

myPool1.Release(pTtmp);

for (int i = 0; i < 30; ++i)
{
struct sTest* pTest3;
pTest3 = (struct sTest*)(myPool1.Get());

pTest3->m_id = 123;
pTest3->m_num = 13445;
cout << pTest3->m_id << "  " << pTest3->m_num << endl << endl;
cout << "myPool1 allocated block num = " << myPool1.Allocated() << endl;
cout << "myPool1 available block num = " << myPool1.Available() << endl;
cout << "myPool1 total block num = " << myPool1.GetBlockNum() << endl << endl;
}

int iWait;
cin >> iWait;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内存池