std :: forward_list-用存储的迭代器擦除

人气:439 发布:2022-10-16 标签: linked-list c++ c++11 forward-list intrusive-containers

问题描述

我试图保留一个特定(基)类实例的全局列表,以便我可以随时通过遍历该全局列表来跟踪它们.

I'm trying to keep a global list of a particular (base) class's instances so that I can track them down by iterating through this global list at any time.

我认为解决这个问题的最合适方法是使用侵入式列表.我听说有人可以通过例如研究Linux内核来遇到这些生物.

I believe the most proper way to address this is with an intrusive list. I have heard that one can encounter these creatures by digging into the Linux kernel, for example.

在我所处的情况下,我实际上并不需要这种性能保证,而使用侵入式列表会使我的事情变得有些复杂.

In the situation where I'm in, I don't really need such guarantees of performance, and using intrusive lists will complicate matters somewhat for me.

到目前为止,这是我实现一个了解所有实例的类的概念的内容.

Here's what I've got so far to implement this concept of a class that knows about all of its instances.

class A {
    static std::forward_list<A*> globallist;
    std::forward_list<A*>::iterator listhandle;
public:
    A() {
        globallist.push_front(this);
        listhandle = globallist.begin();
    }
    virtual ~A() {
        globallist.erase_after(...);  // problem
    }
};

问题是没有forward_list::erase(),而且确实不像将globallist.before_begin()保存在ctor中对我有很大帮助.我绝不应该取消引用before_begin()的迭代器.它实际上会保持住该位置吗?如果我保存before_begin的迭代器,然后保存push_front()一个新项,则该迭代器可能仍然无法取消引用,但是可以发送给erase_after()使用吗?

The problem is that there is no forward_list::erase(), and it really does not appear like saving globallist.before_begin() in the ctor would do me much good. I'm never supposed to dereference before_begin()'s iterator. Will it actually hold on to the position? If I save out before_begin's iterator, and then push_front() a new item, that iterator is probably still not capable of being dereferenced, but will it be serviceable for sending to erase_after()?

推荐答案

forward_list是一个单链表.要在其中删除一个节点,您必须以某种方式拥有一个指向上一个节点的指针.例如,您可以执行以下操作:

forward_list is a singly linked list. To remove a node in the middle of that, you must have a pointer to previous node, somehow. For example, you could do something like this:

class A {
    static std::forward_list<A*> globallist;
    std::forward_list<A*>::iterator prev_node;
public:
    A() {
        A* old_head = globallist.front();
        globallist.push_front(this);
        prev_node = globallist.before_begin();
        old_head->prev_node = globallist.begin();
    }
};

将第一个元素放入一个空列表的情况以及删除逻辑留给读者练习(删除时,将prev_node复制到下一个节点的prev_node).

The case of pushing the first element into an empty list, as well as the removal logic, are left as an exercise for the reader (when removing, copy your prev_node to the next node's prev_node).

或者,只需使用std::list并避免所有此类麻烦.

Or, just use std::list and avoid all this trouble.

220