最近心血来潮想做个内存池类,代码贴出求批评指正!

时间:2021-08-27 00:58:20
自己想实现一个简单的内存池,但是构造的时候有不知道如何下手,下面贴出我理解和构造的简单的类定义与部分实现,望高手指出错误并且给出修改意见,谢谢!
--------------------------------------------------------
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;
}

25 个解决方案

#1


建议找《STL源码剖析》或者《Modern C++ Design》参考它们的内存池。
boost::pool也可以参考参考。

#2


mark

#3


mark之

#4


接:)

#5


学习,帮顶

#6


好好干~,有前途

#7


mark.

#8


这个为什么不用一个template来实现呢?
这样就不用对每种类型都写一个内存池了
我在项目中曾经也写过一个回收站,但是当时用的是void*的方法,现在学了template之后感觉如果用template才是正道。

#9


学习

#10


选择合适的起点,先从阅读别人的代码入手。

#11


感觉不错啊,完善几点就更好了:
1、考虑可重入。
2、可以将错误检测也放进去,比如上溢和下溢的检测、释放未分配的内存检测等,可以更方便的定位问题。
3、建议不要零碎的分配链表节点,防止出现碎片。

#12


mark
不过mark是什么意思?

#13


mark者,标记也

#14


写的不错, 可惜不是template.
你这个是两个链表, 没必要.
看看winx的网站吧

#15


to:SnowOnSahara(花一样)
   首先感谢你的宝贵建议。不过我对你意见的第1条与第3条不太理解,我的功力有限啊,如果给出详细点的就好了,再次感谢,期盼你的答复。

dai_weitao(疯狂Linux C++)
   用template实现是不错的选择,不过俺好久不用C++了,好多技术已经忘记了,等有时间看下template方面的内容我会用template重新写这个池子。你说的winx的网站可否提供下地址,我想看看学习下,谢谢!

#16


帖子沉拉,自己顶下!

#17


d

#18


学习中  帮忙顶一下

#19


收藏,一会看

#20


不知道你的查找采用什么算法 数据量大的时候应该考虑下查找效率

#21


jf

#22


MARK

#23


学习

#24


mark

#25


不知道怎么这么多人说可惜不是模板,模板有的时候不一定是最好的,LPVOID就可以代表一切.模板会增大你的程序,有的时候那是没必要的

#1


建议找《STL源码剖析》或者《Modern C++ Design》参考它们的内存池。
boost::pool也可以参考参考。

#2


mark

#3


mark之

#4


接:)

#5


学习,帮顶

#6


好好干~,有前途

#7


mark.

#8


这个为什么不用一个template来实现呢?
这样就不用对每种类型都写一个内存池了
我在项目中曾经也写过一个回收站,但是当时用的是void*的方法,现在学了template之后感觉如果用template才是正道。

#9


学习

#10


选择合适的起点,先从阅读别人的代码入手。

#11


感觉不错啊,完善几点就更好了:
1、考虑可重入。
2、可以将错误检测也放进去,比如上溢和下溢的检测、释放未分配的内存检测等,可以更方便的定位问题。
3、建议不要零碎的分配链表节点,防止出现碎片。

#12


mark
不过mark是什么意思?

#13


mark者,标记也

#14


写的不错, 可惜不是template.
你这个是两个链表, 没必要.
看看winx的网站吧

#15


to:SnowOnSahara(花一样)
   首先感谢你的宝贵建议。不过我对你意见的第1条与第3条不太理解,我的功力有限啊,如果给出详细点的就好了,再次感谢,期盼你的答复。

dai_weitao(疯狂Linux C++)
   用template实现是不错的选择,不过俺好久不用C++了,好多技术已经忘记了,等有时间看下template方面的内容我会用template重新写这个池子。你说的winx的网站可否提供下地址,我想看看学习下,谢谢!

#16


帖子沉拉,自己顶下!

#17


d

#18


学习中  帮忙顶一下

#19


收藏,一会看

#20


不知道你的查找采用什么算法 数据量大的时候应该考虑下查找效率

#21


jf

#22


MARK

#23


学习

#24


mark

#25


不知道怎么这么多人说可惜不是模板,模板有的时候不一定是最好的,LPVOID就可以代表一切.模板会增大你的程序,有的时候那是没必要的