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

Remove item from a list using its pointer

本文关键字:项目 删除 列表 指针      更新时间:2023-10-16

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

mylist.erase(p);

到目前为止,我只能通过遍历列表直到到达位置p的项目,然后使用erase方法来完成这项工作,这似乎效率很低。

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

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

事实上,你发现自己处于这种情况,这表明设计有问题,因为你是正确的,从收藏中删除物品的唯一方法是完全迭代(即线性复杂性)

以下可能值得考虑:

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

  2. 如果设计允许,请更改所指向的项以包含"已删除"标志(或使用模板提供此标志),这样可以避免从集合中删除对象,但可以快速将其标记为已删除。缺点是您的所有软件都必须更改以适应这种约定。

  3. 如果这是线性搜索的唯一一点,并且集合不多(比如说<20个项目。)为了方便起见,只需按照你的建议进行线性搜索,但在代码中留下一个大注释,表明你是如何">完全得到"这是多么低效。你可能会发现,在任何情况下,这在一段时间内都不会成为一个明显的问题,如果有的话。

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

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

只有当你准备好进入未定义行为和不可移植的禁忌世界时才阅读:

有一种不可移植的方法可以使迭代器从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的包装。

无法完成。

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

std::list不允许通过指针删除元素,这似乎真的很愚蠢,因为显然有下一个和上一个指针。

我正在考虑重新使用Linux内核LIST宏来解决这个问题。过于抽象的问题是,您必须放弃与较低级别api的互操作性和通信。