使用指针从列表中删除项目

时间:2012-09-18 14:32:12

标签: c++ list pointers iterator

我有一个指针p(不是迭代器)到列表中的项目。然后我可以使用p从列表中删除(擦除)项目吗?类似的东西:

mylist.erase(p);

到目前为止,我只能通过遍历列表直到我到达位置p的项目,然后使用erase方法来执行此操作,这似乎非常低效。

4 个答案:

答案 0 :(得分:8)

不,你必须使用迭代器。我不明白为什么获取指针比获取迭代器更容易...

答案 1 :(得分:3)

std::list不是关联的,因此您无法使用指针作为键直接删除特定元素。

你发现自己处于这种情况的事实指向可疑设计,因为你是正确的,从集合中删除项目的唯一方法是完全迭代它(即线性复杂性)

以下可能值得考虑:

  1. 如果可能,您可以将列表更改为std::multiset(假设有重复的项目),这将使直接访问更有效。

  2. 如果设计允许,请更改您指向的项目以包含“已删除”标记(或使用模板提供此标记),以避免从集合中删除对象但快速标记删除。缺点是您的所有软件都必须更改以适应此惯例。

  3. 如果这是线性搜索的唯一一点而且收集量不大(< 20项说)。为了方便起见,只需按照你的建议进行线性搜索,但留下一个大评论在代码中指出你如何“完全获得”这是多么低效。你可能会发现,如果有的话,这在任何情况下都不会成为一个有形的问题。

  4. 我猜这3可能是你最好的选择。 :)

答案 2 :(得分:0)

这不是我的建议,只是为了回答这个问题:

只有在您准备进入未定义行为和不可移植性的禁止世界时才能读取:

T*指针到list<T>中的元素,有一种不可移植的方法来创建迭代器。您需要查看std库list头文件。对于Gnu g++,其中包含stl_list.h std::list定义。最典型的std::list<T>由与此类似的节点组成:

template <class T>
struct Node {
   T item;
   Node* prev;
   Node* next;
};

指向Node<T>::item的指针,您可以使用offsetof计算此节点指针。请注意,此Node模板可能是std::list的私有部分,因此您必须破解此项 - 比如使用不同的名称定义相同的结构模板。 std::list<>::iterator只是这个node的包装。

答案 3 :(得分:0)

无法完成。

我遇到类似的问题,因为我使用了epoll_wait并处理了一系列事件。事件结构只包含一个联合,其中最明显的类型是void *,用于指示找到的相关数据(包括文件描述符)。

std :: list似乎非常愚蠢,因为显然有下一个和前一个指针,所以它不允许你通过指针删除一个元素。

我考虑重新使用Linux内核LIST宏来解决这个问题。抽象过多的问题在于你必须放弃与低级别apis的互操作性和沟通。