5

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

mylist.erase(p);

到目前为止,我只能通过遍历列表直到到达 location 处的项目p,然后使用该erase方法来做到这一点,这似乎非常低效。

4

4 回答 4

9

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

于 2012-09-18T14:34:31.780 回答
3

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

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

以下可能值得考虑:

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

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

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

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

于 2012-09-18T14:52:45.063 回答
1

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

仅当您准备好进入未定义行为和不可移植性的禁止世界时才阅读:

有一种不可移植的方法可以从T*指向 a 中元素的指针生成迭代器list<T>。您需要查看您的标准库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

于 2012-09-18T17:59:27.667 回答
0

这是不可能的。

我有一个类似的问题,因为我正在使用 epoll_wait 并处理事件列表。events 结构仅包含一个 union,其中最明显的使用类型是 void * 以指示找到的相关数据(包括文件描述符)。

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

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

于 2017-09-23T02:05:06.857 回答