我有一个可能最终出现在多个列表中的对象。
例如
std::list<object*> lista = new std::list<object*>();
std::list<object*> listb = new std::list<object*>();
object* obj = new object();
lista->push_front(obj);
listb->push_front(obj);
潜在地,有许多对象将以相同的方式在两个列表中结束。我意识到智能指针很容易做到,但我称之为受虐狂 - 我更愿意在没有它的情况下弄明白。
目前,我正在尝试这种技术:
td::list<object*>::iterator iter;
for(iter = lista->begin(); iter != lista->end(); iter++) {
delete (*iter);
*iter = 0;
}
std::list<object*>::iterator iterB;
for(iterB = listb->begin(); iterB != listb->end(); iterB++) {
if(*iterB != 0) {
delete (*iterB);
*iter = 0;
}
}
delete lista;
delete listb;
但它在运行时相当于delete lista;
。希望有人能更聪明地指点指针可以帮助我。提前谢谢!
P.S。我正在运行Windows 7 / MinGW。
答案 0 :(得分:3)
一个主要问题是你(显然,你没有提供完整的代码)delete
一个对象两次:一次迭代列表A,一次迭代列表B。
主要有三种解决方案:
使用像std::shared_ptr
这样的引用计数智能指针
推荐的。你不想使用智能指针的陈述似乎是出于无知,而不是一些愚蠢的经理的要求。
将节点保留在主列表中:
delete
节点只有当您知道它仍然存在的唯一列表时才是主列表。
自己实施参考计数:
最简单的方法是再次使用现有的库解决方案,例如boost::intrusive_ptr
,但您所要做的就是在每个节点中精心维护引用计数。引用计数降至0时delete
。
第四种可能性是使用诸如Boehm收集器之类的垃圾收集器,但是代码需要被构造为支持它。或者至少那是我的印象。而且可能很难得到帮助,因为很少有C ++程序员使用这种方法(这表明它并非完全没有问题)。
答案 1 :(得分:1)
使用shared_ptr
或拥有unique_ptr
的主列表。
如果失败,请拥有一个拥有指针的主列表,并在清除后从中删除但不删除所有其他列表。
如果不这样做,请不要直接从列表中直接删除。而是insert
你想要的指针进入std::set
,并在删除之前从其他列表中删除它们(迭代并在集合中查找),或者累积你想要处理的所有指针然后质量从集合中删除它们。
这是按段落的粗略顺序。
答案 2 :(得分:0)
不确定为什么你真的不想使用shared_ptr。好适合自己。你怎么只创建一个本地shared_ptr?如果没有,则将列表加载到一个主列表中。清除两个子列表,并删除主列表中的每个元素以及清除主列表。
答案 3 :(得分:0)
在第
行if(*iterB != 0) {
* iterB永远不会是0.所以你是双重删除。
答案 4 :(得分:0)
将计数器字段添加到object
。默认初始化为0.添加到列表时添加+1。 -1从列表中删除。如果counter==0
,请删除object
。
这不是shared_ptr
的线程安全,但出于同样的原因它可以快得多。