简体   繁体   English

删除多个列表指向的数据?

[英]Deleting data that is pointed to by multiple lists?

I have a an object that will potentially end up in multiple lists. 我有一个可能最终出现在多个列表中的对象。

For example 例如

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);

Potentially, there are many objects that will end up in both lists in the same way. 潜在地,有许多对象将以相同的方式在两个列表中结束。 I realize smart pointers would be the easy thing to do, but call me a masochist - I'd prefer to figure out how to do it without. 我意识到聪明的指针很容易做到,但我称之为受虐狂 - 我更愿意在没有的情况下弄清楚如何做到这一点。

Currently, I'm trying this technique: 目前,我正在尝试这种技术:

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;

But it breaks on my equivalent of delete lista; 但它打破了我的delete lista; at run time. 在运行时。 Hopefully someone out there smarter about pointers can help me out. 希望有人能更聪明地指点指针可以帮助我。 Thanks in advance! 提前致谢!

PS I'm running Windows 7/MinGW. PS我正在运行Windows 7 / MinGW。

A main problem is that you (apparently, you do not offer complete code) delete an object twice: once when iterating through list A, and once when iterating through list B. 一个主要的问题是你(显然,你没有提供完整的代码) delete一个对象两次:一次迭代列表A,一次迭代列表B.

There are three main solutions: 主要有三种解决方案:

  • Use a ref-counting smart pointer like std::shared_ptr . 使用像std::shared_ptr这样的引用计数智能指针。
    Recommended. 推荐的。 Your statement that you do not want to use a smart pointer seems to be made out of ignorance rather than some silly-manager's requirement. 你不想使用智能指针的陈述似乎是出于无知,而不是一些愚蠢的经理的要求。

  • Keep the nodes also in a primary list: 将节点保留在主列表中:
    delete a node only when you know that the only list it's still in, is the primary list. 仅当您知道它仍在的唯一列表是主列表时才delete节点。

  • Implement a reference count yourself: 自己实施引用计数:
    The easiest is again to use an existing library solution such as boost::intrusive_ptr , but all you have to do is to meticulously maintain a reference count in each node. 最简单的方法是再次使用现有的库解决方案,例如boost::intrusive_ptr ,但您所要做的就是在每个节点中精心维护引用计数。 delete when the reference count goes down to 0. 当引用计数降为0时delete

A fourth possibility is to use a garbage collector such as the Boehm collector, but then the code needs to be structured to support it. 第四种可能性是使用垃圾收集器,例如Boehm收集器,但是代码需要构造成支持它。 Or at least that's my impression. 或者至少那是我的印象。 And it may be difficult to get help with that, since very few C++ programmers use that approach (which indicates that it's not entirely free of problems). 而且可能很难得到帮助,因为很少有C ++程序员使用这种方法(这表明它并非完全没有问题)。

Use shared_ptr or have a master list with unique_ptr . 使用shared_ptr或具有unique_ptr的主列表。

Failing that, have a master list that owns the pointers, and delete from it after you clear but do not delete all other lists. 如果失败,请拥有一个拥有指针的主列表,并在清除后从中删除但不删除所有其他列表。

Failing that, do not directly delete from a list directly. 如果不这样做,请不要直接从列表中删除。 Instead insert the pointers you want gone into a std::set , and either remove them from the other lists before deleting (iterate and find in the set), or accumulate all the pointers you want to dispose of then mass delete them from the set. 而是insert你想要的指针insertstd::set ,然后在删除之前从其他列表中删除它们(迭代并在集合中查找),或者累积你想要处理的所有指针然后从集合中大量删除它们。

This is in rough order of suckitude by paragraph. 这是按段落的粗略顺序。

Not sure why you don't really want to use shared_ptr. 不确定为什么你真的不想使用shared_ptr。 Ok suit yourself. 好适合自己。 How about you just create a local shared_ptr? 你怎么只创建一个本地shared_ptr? If not then load both the list into one master list. 如果没有,则将列表加载到一个主列表中。 Clear the two sublist, and delete each element in the master list as well as clearing the master list. 清除两个子列表,并删除主列表中的每个元素以及清除主列表。

In the line 在线

if(*iterB != 0) {

*iterB will never be 0. So you are double deleting. * iterB永远不会是0.所以你是双重删除。

Add counter field to your object . 向您的object添加计数器字段。 Default initialize to 0. Add +1 on adding to a list. 默认初始化为0.添加到列表时添加+1。 -1 on removal from a list. -1从列表中删除。 If counter==0 , delete the object . 如果counter==0 ,则删除该object

This is not thread safe as shared_ptr , but it can be much faster for the same reason. 这与shared_ptr不是线程安全的,但出于同样的原因它可以快得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM