【问题标题】:Remove item from a list using its pointer使用其指针从列表中删除项目
【发布时间】:2012-09-18 14:32:12
【问题描述】:

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

mylist.erase(p);

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

【问题讨论】:

  • 请说明您对指针的使用。列表是否以指针类型为模板?
  • 效率低下的原因是因为您以错误的方式处理问题(可能是整个 C++)。您应该从一开始就通过迭代器处理列表元素! (你来自 C 或汇编程序背景?)
  • ^ 这个……想想吧
  • @KerrekSB 是的,最好传递列表迭代器而不是指针或对列表元素的引用。但是在我当前的项目中,我想编写一个库,它向“外部世界”提供对象(而不是指向对象的迭代器),但仍需要跟踪分配给它的所有对象。解决方案是手动将列表功能编码到分配的对象中(通过添加一些 prev/next 指针)或在搜索正确的迭代器时继续遍历 C++ list

标签: c++ list pointers iterator


【解决方案1】:

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

【讨论】:

  • 谢谢,我意识到我之前在代码中将迭代器转换为指针,因此我可以使用原始迭代器
【解决方案2】:

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

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

以下可能值得考虑:

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

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

  3. 如果这是唯一的线性搜索并且集合不大(完全了解”这是多么低效。您可能会发现这在任何情况下都不会成为一个有形的问题,如果有的话。

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

【讨论】:

  • 谢谢。由于给定的选项范围,将其标记为已接受。
【解决方案3】:

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

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

有一种不可移植的方法可以使迭代器从T* 指针指向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&lt;T&gt;::item 的指针,您可以使用offsetof 计算此节点指针。请注意,这个Node 模板可能是std::list 的私有部分,所以你必须破解它 - 比如说定义具有不同名称的相同结构模板。 std::list&lt;&gt;::iterator 只是这个node 的包装。

【讨论】:

    【解决方案4】:

    这是做不到的。

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

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

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

    【讨论】:

      猜你喜欢
      • 2012-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-15
      • 2022-12-20
      • 2012-02-01
      • 1970-01-01
      相关资源
      最近更新 更多