最近在研究c++的内存自动回收方式,发现auto_ptr并不能自动回收数组内存,给内存管理带来一定的麻烦,因而为了解决此问题,研究得到可以使用数据结构与对象的方式进行改造,以实现动态内存数组的回收,以下为实现的代码,实际测试中并没有发现存在内存增长的情况,可以作为参考:
#include <wtypes.h>
#include <windef.h>
#include <winbase.h>
#include <memory>
#include <iostream>
#include <stdio.h>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
class CData;
typedef void (*CDATARELEASE)(CData* pthis);
//动态分析内存自动回收处理类
class CData
{
public :
template<typename T>
static void vCDataRelease(CData* pthis)
{
cout<<"vCDataRelease call begin <<"<<typeid(T).name()<<endl;
if (NULL != pthis->pPoint)
{
cout<<"vCDataRelease point ok! <<"<<endl;
if(pthis->lNum>1)
delete[] (T*)pthis->pPoint;
else if(pthis->lNum==1) delete (T*)pthis->pPoint;
}
cout<<"vCDataRelease call end >>>"<<endl;
}
public:
CData()
{
pPoint = NULL;
lNum = 0;
pRelease = NULL;
}
CData(void* pParam,long nNum,CDATARELEASE pFun)
{
pPoint = pParam;
lNum = nNum;
pRelease = pFun;
}
virtual ~CData()
{
if(pRelease==NULL)
{
if (NULL != pPoint)
{
if(lNum>1)
delete[] pPoint;
else if(lNum==1)
delete pPoint;
}
}
else
pRelease(this);
pPoint = NULL;
}
protected:
public:
void* pPoint;
long lNum; //注意:这里为元素个数,并不是字节数,如class A时为1,class A[4]时为4
CDATARELEASE pRelease;
};
//数据块节点定义
typedef struct _tDataBlock
{
_tDataBlock()
{
pPrev = NULL;
pNext = NULL;
}
_tDataBlock* pPrev;
_tDataBlock* pNext;
auto_ptr<CData> pdata; //请注意 auto_ptr 所有权会转换,请注意使用规则
long nDataByteSize;
}tDataBlock;
class myclass
{
public:
myclass()
{
cout<<"myclass begin <<"<<endl;
pbuffer = new char[1024*3];
}
~myclass()
{
cout<<"myclass end >>>>>>"<<endl;
delete[] pbuffer;
}
private:
char* pbuffer;
};
int main()
{
//test class and void*
int i = 0;
for(i=0;i<100000;i++)
{
cout<<"new myclass begin....."<<i<<endl;
Sleep(1000);
{
long l_nNum = 3;
myclass* l_ptestmem = new myclass[l_nNum];
auto_ptr<CData> l_cmdptr(new CData(l_ptestmem,l_nNum,CData::vCDataRelease<myclass>));
tDataBlock l_tDataBlock;
l_tDataBlock.pdata = l_cmdptr;
l_tDataBlock.nDataByteSize = l_nNum*sizeof(myclass);
cout<<"delete myclass begin....."<<endl;
//Sleep(10000);
}
cout<<"delete myclass end....."<<endl;
//Sleep(10000);
cout<<"new char begin....."<<endl;
{
long l_nNum = 1024*300;
char* l_ptestmem = new char[l_nNum];
auto_ptr<CData> l_cmdptr(new CData(l_ptestmem,l_nNum,CData::vCDataRelease<char>));
tDataBlock l_tDataBlock;
l_tDataBlock.pdata = l_cmdptr;
l_tDataBlock.nDataByteSize = l_nNum*sizeof(char);
cout<<"delete char begin....."<<endl;
//Sleep(10000);
}
cout<<"delete char end....."<<endl;
//Sleep(10000);
cout<<"all end....."<<endl;
}
return 0;
}
若有什么问题,请评论。
PS:值得注意的是:void* point指针指向的数组,如果不使用明确的类型进行delete时,会仅delete成功1个“对象”,因此会带来内存泄漏,但此处使用了模板函数解决了此问题。