读书人

最近心血来潮想做个内存池类代码贴出

发布时间: 2012-02-13 17:20:26 作者: rapoo

最近心血来潮想做个内存池类,代码贴出求批评指正!
自己想实现一个简单的内存池,但是构造的时候有不知道如何下手,下面贴出我理解和构造的简单的类定义与部分实现,望高手指出错误并且给出修改意见,谢谢!
--------------------
CMemPool.h

#ifndef __CMEMPOOL_H__
#define __CMEMPOOL_H__

#include <string>
using namespace std;

const int INTDEFBLOCKSIZE = 8; ///内存扩容与收缩的数量级

struct StringLink ////定义字符型内存的链表结构
{
StringLink * next;
bool m_bIsUse;
string m_strDataName;
string m_strDataValue;
};

struct IntLink ////定义数值型内存的链表结构
{
IntLink * next;
bool m_bIsUse;
string m_strDataName;
int m_intDataValue;
};

class CMemPool{
protected:
int m_intSizeString; ///字符内存链表的长度
int m_intSizeInt; ///数值内存链表的长度
int m_intSizeStringFree; ///字符内存空闲结点数量
int m_intSizeIntFree; ///数值内存空闲结点数量
bool m_bMutex; ///内存池的锁变量
StringLink * m_pStringLinkFree; ///始终指向字符内存中空闲结点的指针
StringLink * m_pStringLinkHead; ///指向字符内存链表头结点的指针
IntLink * m_pIntLinkFree; ///始终指向数值内存中空闲结点的指针
IntLink * m_pIntLinkHead; ///指向数值内存链表头结点的指针

public:
////构造函数,执行2种类型的内存链表的构造与初始化,初始化成员变量的值,
////执行过程期间为锁定状态,执行完毕解锁。
CMemPool(void);

////查找一个字符内存的空闲结点,使用找到的空闲结点
virtual int UseStringData(string, string) = 0;

////查找一个数值内存的空闲结点,使用找到的空闲结点
virtual int UseIntData(string, int) = 0;

////放弃对应名称字符型结点的使用,使之成为空闲结点
virtual int UnuseStringData(string) = 0;

////放弃对应名称数值型结点的使用,使之成为空闲结点
virtual int UnuseIntData(string) = 0;

////取得对应名称字符型结点内储存的值
virtual int GetStringData(string, string&) = 0;

////取得对应名称数值型结点内储存的值
virtual int GetIntData(string, int&) = 0;

////析构函数,功能与构造函数相反
~CMemPool(void);
protected:
////当字符型内存链表的空闲结点不够使用时扩展字符型内存链表的长度
virtual int ExtendStringLink(void) = 0;

////当数值型内存链表的空闲结点不够使用时扩展数值型内存链表的长度
virtual int ExtendIntLink(void) = 0;

////当字符型内存链表的空闲结点过多是收缩字符型内存链表
virtual int UnextendStringLink(void) = 0;

////当数值型内存链表的空闲结点过多时收缩数值型内存链表
virtual int UnextendIntLink(void) = 0;



////在字符型内存链表中查找相应名称的结点
virtual int FindStringData(string, StringLink *) = 0;

////在数值型内存链表中查找相应名称的结点
virtual int FindIntData(string, IntLink *) = 0;
};

#endif


----------------------------
CMemPool.cpp

#include "CMemPool.h "

CMemPool::CMemPool(void)
{
m_bMutex = false; ///加琐

m_intSizeString = INTDEFBLOCKSIZE;
m_intSizeInt = INTDEFBLOCKSIZE;
m_intSizeStringFree = INTDEFBLOCKSIZE;
m_intSizeIntFree = INTDEFBLOCKSIZE;
m_pStringLinkFree = 0;
m_pStringLinkHead = 0;
m_pIntLinkFree = 0;
m_pIntLinkHead = 0;

////构造字符内存链表
StringLink * pOldStringNode = 0; ///记录前一个节点地址。
for(int intIndexTem = 0; intIndexTem < m_intSizeString - 1; ++intIndexTem)
{
StringLink * pNewCreateStringNode = 0;
pNewCreateStringNode = new StringLink;

//////?防止new申请内存失败,保证申请内存成功!
while(pNewCreateStringNode=0)
{
pNewCreateStringNode = new StringLink;
}
//////?end

/////清空新申请内存中的垃圾数据
pNewCreateStringNode -> next = 0;
pNewCreateStringNode -> m_bIsUse = false;
pNewCreateStringNode -> m_strDataName.erase();
pNewCreateStringNode -> m_strDataValue.erase();


if(m_pStringLinkHead = 0)
m_pStringLinkHead = pNewCreateStringNode;
if(m_pStringLinkFree = 0)
m_pStringLinkFree = pNewCreateStringNode;

////建立实际字符链表try{
if(pOldStringNode = 0)
pOldStringNode = pNewCreateStringNode;
else
{
pOldStringNode -> next = pNewCreateStringNode;
pOldStringNode = pNewCreateStringNode;
}
///}catch()

pNewCreateStringNode = NULL;
}
pOldStringNode = NULL;

////构造整数内存链表
IntLink * pOldIntNode = 0; ///记录前一个节点地址。
for(intIndexTem = 0; intIndexTem < m_intSizeInt - 1; ++intIndexTem)
{
IntLink * pNewCreateIntNode = 0;
pNewCreateIntNode = new IntLink;

/////?保证new申请内存成功
while(pNewCreateIntNode = 0)
{
pNewCreateIntNode = new IntLink;
}
////?end


/////清空新申请内存中的垃圾数据
pNewCreateIntNode -> next =0;
pNewCreateIntNode -> m_bIsUse = false;
pNewCreateIntNode -> m_strDataName.erase();
pNewCreateIntNode -> m_intDataValue = 0 ;


if(m_pIntLinkHead = 0)
m_pIntLinkHead = pNewCreateIntNode;
if(m_pIntLinkFree = 0)
m_pIntLinkFree = pNewCreateIntNode;

////建立实际整数链表try{
if(pOldIntNode = 0)
pOldIntNode = pNewCreateIntNode;
else
{
pOldIntNode -> next = pNewCreateIntNode;
pOldIntNode = pNewCreateIntNode;


}
///}catch()

pNewCreateIntNode = NULL;
}
pOldIntNode = NULL;

m_bMutex = true; ///解琐
}


CMemPool::~CMemPool(void)
{
m_bMutex = false;

m_pIntLinkFree = NULL;
m_pStringLinkFree = NULL;

IntLink * pNextIntNode = 0;
for(int intIndexTem = 0; intIndexTem < m_intSizeInt - 1; ++intIndexTem)
{

pNextIntNode = m_pIntLinkHead -> next;
delete m_pIntLinkHead;
m_pIntLinkHead = pNextIntNode;

}
pNextIntNode = NULL;

StringLink * pNextStringNode = 0;
for(intIndexTem = 0; intIndexTem < m_intSizeString - 1; ++intIndexTem)
{

pNextStringNode = m_pStringLinkHead -> next;
delete m_pStringLinkHead;
m_pStringLinkHead = pNextStringNode;

}
pNextStringNode = NULL;

m_pStringLinkHead = NULL;
m_pIntLinkHead = NULL;

m_intSizeString = 0;
m_intSizeInt = 0;
m_intSizeStringFree = 0;
m_intSizeIntFree = 0;

m_bMutex = true;
}

[解决办法]
建议找《STL源码剖析》或者《Modern C++ Design》参考它们的内存池。
boost::pool也可以参考参考。
[解决办法]
这个为什么不用一个template来实现呢?
这样就不用对每种类型都写一个内存池了
我在项目中曾经也写过一个回收站,但是当时用的是void*的方法,现在学了template之后感觉如果用template才是正道。
[解决办法]
感觉不错啊,完善几点就更好了:
1、考虑可重入。
2、可以将错误检测也放进去,比如上溢和下溢的检测、释放未分配的内存检测等,可以更方便的定位问题。
3、建议不要零碎的分配链表节点,防止出现碎片。
[解决办法]
写的不错, 可惜不是template.
你这个是两个链表, 没必要.
看看winx的网站吧

读书人网 >C++

热点推荐