4

我有一个可能会出现在多个列表中的对象。

例如

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;在运行时中断了我的等价物。希望那里的指针更聪明的人可以帮助我。提前致谢!

PS 我正在运行 Windows 7/MinGW。

4

5 回答 5

3

一个主要问题是您(显然,您没有提供完整的代码)delete一个对象两次:一次是在遍历列表 A 时,一次是在遍历列表 B 时。

解决方案主要有以下三种:

  • 使用引用计数智能指针,例如std::shared_ptr.
    受到推崇的。您不想使用智能指针的声明似乎是出于无知而不是某些愚蠢的经理的要求。

  • 将节点也保留在主列表中:
    delete仅当您知道它仍在其中的唯一列表时,节点才是主列表。

  • 自己实现引用计数:
    最简单的方法是再次使用现有的库解决方案,例如boost::intrusive_ptr,但您所要做的就是精心维护每个节点中的引用计数。delete当引用计数下降到 0 时。

第四种可能性是使用垃圾收集器,例如 Boehm 收集器,但代码需要结构化以支持它。或者至少这是我的印象。而且可能很难获得帮助,因为很少有 C++ 程序员使用这种方法(这表明它并非完全没有问题)。

于 2012-12-29T04:15:36.087 回答
1

使用shared_ptr或拥有一个主列表unique_ptr

如果做不到这一点,请拥有一个拥有指针的主列表,并在清除后从中删除,但不要删除所有其他列表。

否则,不要直接从列表中直接删除。相反insert,您想要的指针进入 a std::set,并在删除之前将它们从其他列表中删除(迭代并在集合中查找),或者累积您想要处理的所有指针,然后从集合中批量删除它们。

这是按段落的粗略顺序。

于 2012-12-29T04:10:35.003 回答
0

不知道为什么你真的不想使用 shared_ptr。好吧适合自己。你创建一个本地 shared_ptr 怎么样?如果没有,则将两个列表都加载到一个主列表中。清除两个子列表,并删除主列表中的每个元素以及清除主列表。

于 2012-12-29T03:54:41.570 回答
0

在行

if(*iterB != 0) {

*iterB 永远不会为0。所以你是双重删除。

于 2012-12-29T05:11:29.513 回答
0

将计数器字段添加到您的object. 默认初始化为 0。添加到列表时添加 +1。-1 从列表中删除。如果counter==0,删除object.

这不是线程安全的shared_ptr,但出于同样的原因,它可以更快。

于 2012-12-29T05:38:36.460 回答