JAVA,C sharp的supporter经常拿语言特有的垃圾回收器说事.C++是万能的!当然前提是使用它的人必须先是全能的.
下例是以青年人网站现在浅薄的C++掌握水平所实现的基于标记-清除算法的GC.如果类对象想实现自动回收其内存,其必须派生自Collectable类,并且实现Collectable的GetReference虚函数,由于我是无法预知派生类的指针或引用成员变量,所以采用template设计模式依赖倒置.
简单示意:
void Class1::GetReference()
{
m_reftoClass2 ->doMark();//标记其引用对象
or return;//如果没有引用对象,同时递归终止
}
#ifndef _GC
#define _GC
#pragma once
#include <vector>
#include <iterator>
using namespace std;
class Collectable;
class GarbageCollector{
typedef vector<Collectable *> MEMPOOL;
public:
//the public interface to the client
static GarbageCollector *GetInstance(void)
{
if(!iSelf)
return (iSelf = new GarbageCollector());
return iSelf;
}
static void Add2GC(Collectable *obj);
void GarbageCollection(Collectable *rootObj);
private:
GarbageCollector()
{
}
void Mark(Collectable *obj);
void Sweep();
MEMPOOL iMemPool;
static GarbageCollector *iSelf;//the only instance of GC class
};
class Collectable{
friend class GarbageCollector;
public:
Collectable(bool mark = 0):iMarkBit(mark){}
virtual ~Collectable(){}
void doMark(void)
{
if(!iMarkBit)
{
iMarkBit = true;
GetReference();
GarbageCollector::Add2GC(this);
}
}
virtual void GetReference() = 0;
protected:
bool iMarkBit;//Mark for GC
};
GarbageCollector *GarbageCollector::iSelf = NULL;
void GarbageCollector::Add2GC(Collectable *obj)
{
(iSelf->iMemPool).push_back(obj);
}
void GarbageCollector::Mark(Collectable *obj)
{
if(obj)
obj->doMark();
}
void GarbageCollector::Sweep()
{
for(MEMPOOL::iterator vIter = iMemPool.begin(); vIter != iMemPool.end();)
{
Collectable *temp = *vIter;
//Here it's the data used by other data
if(temp->iMarkBit)
{
temp->iMarkBit = false;
vIter++;
}
else
{
//Discard the useless data block and adjust iterator to proper position
vIter = iMemPool.erase(vIter);
//free the memory or push the space into memory pool
delete temp;
}
}
}
void GarbageCollector::GarbageCollection(Collectable *rootObj)
{
if(rootObj)
{
Mark(rootObj);
Sweep();
}
}
#endif
本例其实存在隐患,即有可能stack overflow.因为doMark->GetReference->doMark... ...递归扫描,而且Collectable和GarbageCollector双向耦合,耦合度高.另外在清除标记为0(即不再被引用的对象)时,只是简单释放给系统堆.如果内重载operator delete(void *)使之仅仅归还给Memory Pool其价值更高.其实在寸土寸金的嵌入式设备中,内寸很容易耗尽,GC的价值应该被集成到系统的内存管理器中,哎,继续学习Symbian中,因为还没有看到它的内存管理策略是什么.
责任编辑:小草