返回信息流// Collect garbage. Returns true if at least
// one object was freed.
template <class T, int size> bool GCPtr<T, size>::collect()
{
bool memfreed = false;
#ifdef DISPLAY
cout << "Before garbage collectiing for";
showlist();
#endif
list<GCInfo<T> >::iterator p;
do {
// Scan gclist looking for unreferenced pointers.
for (p = gclist.begin(); p != gclist.end(); p++) {
// if in-use, skip.
if (p->refcount > 0) continue;
memfreed = true;
// Remove unused entry from gclist.
//gclist.remove();
这个地方有点伤神了,还好诺基亚宣讲会前赶出来了
} while (p != gclist.end());
#ifdef DISPLAY
cout << "After garbage collection for ";
showlist();
#endif
return memfreed;
}[em22]
这是一条镜像帖。来源:北邮人论坛 / cpp / #5412同步于 2008/4/21
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
[高兴]完成了第一个Garbage Collector
grepf
2008/4/21镜像同步7 回复
订阅后,新回复会通过你的通知中心匿名送达。
7 条回复
【 在 grepf 的大作中提到: 】
: // Collect garbage. Returns true if at least
: // one object was freed.
: template <class T, int size> bool GCPtr<T, size>::collect()
: ...................
[em68]有想法
能举个例子说明一下是怎么用的吗 ?
数组和单对象的混合使用还是有些问题,正在想办法解决
【 在 UnitTest 的大作中提到: 】
: [em68]有想法
: 能举个例子说明一下是怎么用的吗 ?
这么做是可以的,但存在一个问题:效率有点低了,我现在为了看回收过程故意显示调用了collect()函数;主要是考虑扩展,比如做成后台模式,等待CPU空闲或者内存占用太多时再收集显然好一些。
GCPtr里面的list是静态成员,为的是每种类型使用一个条目列表(GCPtr<TPDObject>和GCPtr<int>因类型不同可以生成不同的条目列表),条目绑定了引用计数和动态分配的内存地址。
【 在 UnitTest 的大作中提到: 】
: 为什么用一个list保存起来,而不是在GCPtr的析构函数里面当判断引用计数为0的时候直接把内存释放掉 ?这么做有什么优势吗 ?
【 在 grepf 的大作中提到: 】
: 这么做是可以的,但存在一个问题:效率有点低了,我现在为了看回收过程故意显示调用了collect()函数;主要是考虑扩展,比如做成后台模式,等待CPU空闲或者内存占用太多时再收集显然好一些。
: GCPtr里面的list是静态成员,为的是每种类型使用一个条目列表(GCPtr<TPDObject>和GCPtr<int>因类型不同可以生成不同的条目列表),条目绑定了引用计数和动态分配的内存地址。
有一种常见情况,当引用链形成一个闭环的时候,你是怎么处理的?简单点说就是,假如new了两个对象a和b都放在GCPtr中,然后在对象a中又通过GCPtr<B>引用了b,而在对象b中通过GCPtr<A>引用了a。当两个对象同时超出作用域的时候,你是如何来判定它们都成为垃圾的?
用作用域限制,一出域,引用计数归0。
给你看看这个代码,希望能明白我的意思。
GCPtr<TClient> client;
if (client == NULL) {
//根据订单ID构造对象(订单、客户、库存项)
client = new TClient();
}
client->Load(ID);
//把对象的信息显示在界面上
LoadObjectToForm();
补充一下:
TClient里面组合了一大堆其它类别东西,如订单类啊,还有数据管理类啊,等等。并且
这里面有循环索引。
另外,这种解决方案我也不满意,我想采用标记删除算法,看了些书,还是不行,水平所限,慢慢改吧,唉,这次修改步履维艰。。。
【 在 UnitTest 的大作中提到: 】
: 有一种常见情况,当引用链形成一个闭环的时候,你是怎么处理的?简单点说就是,假如new了两个对象a和b都放在GCPtr中,然后在对象a中又通过GCPtr<B>引用了b,而在对象b中通过GCPtr<A>引用了a。当两个对象同时超出作用域的时候,你是如何来判定它们都成为垃圾的?
【 在 grepf 的大作中提到: 】
: 用作用域限制,一出域,引用计数归0。
: 给你看看这个代码,希望能明白我的意思。
: GCPtr<TClient> client;
: ...................
呵呵,看来你已经意识到了。引用计数就仅仅只能计数,并不能指出被引用的次数里面有多少是有效的,尤其是面对“垃圾”间的相互引用更是束手无策,而通过作用域限制也并没有完全解决问题。换句话说,如果引用计数真的是可以有效解决这个问题,那标准C++早就该加入GC了。所以容许我不客气地说一句,你当前所实现的不能算是一个GC,只能算是一个强化版的引用计数解决方案。
也许我们应该重新定义一下"垃圾",那就是无法从以根对象作为起点的引用链上找到的对象。根对象就是在main函数里面被构造的对象或者是全局对象。看来一个GC是没有办法避免遍历整个对象引用链的。而GC的最大时间消耗就是在遍历上面,当然和你那个list的遍历是两回事了。而对于.net实现的GC,它还得做碎片整理,因为它是在一块连续的空间上做分配的,但是它采用的是类似堆栈的分配方式,所以分配速度很快。
很期待看到你下个版本[em22]