【问题标题】:Container that does not invalidate iterators (and pointers)不会使迭代器(和指针)失效的容器
【发布时间】:2015-02-08 09:27:59
【问题描述】:

我目前正在寻找提供一些插入(insert 或 push_back)和一些删除(erase,pop_back 不够)方法的容器,并且在调用这两种方法时不会使迭代器或指针无效。

更清楚地说,我想要一组元素,我可以在其中添加一个元素(我不在乎在哪里),在哪里我可以删除任何元素(所以我在乎在哪里)。此外,我会有指向特定元素的外部指针,如果我从集合中添加或删除元素,我希望它们保持有效。

据我所知,有两个标准容器可以满足我的需求:setlist。但是,一般来说,我不喜欢将这样的容器用于这种简单的需求。由于 list 在内部涉及指针并且不提供对其元素的随机访问,我认为这不是一个好的选择。 set 可以随机访问其元素,但也涉及指针,并且随机访问本身并不是在恒定时间内完成的。我认为set 会是比list 更好的解决方案,但我已经考虑过别的了。

当一个元素被移除时,一个简单的向量不会试图保持元素连续呢?当移除这个容器中间的一个元素时,它的位置会是空的,并且不会发生其他任何事情。这样,没有迭代器或指针会失效。另外,添加元素时,容器会搜索空位置,如果没有空位置,则使用简单的push_back

显然,由于push_back 可以使带有vector 的迭代器无效,我将使用deque 作为实现的基础。我还会使用某种堆栈来跟踪删除元素的孔。这样,除了满足我的不失效需求外,添加、删除和访问元素将在恒定时间内完成。

然而,仍然存在一个问题:当迭代这个容器或简单地通过索引访问一个元素时,我们需要考虑这些漏洞。这就是问题开始超越优势的地方。

因此我的问题是:您如何看待我对那个容器的想法? 更重要的是,你会用什么来解决我原来的问题,setlist 或其他什么? 此外,如果您对最后一个问题(迭代我的容器)有一个很好且干净的解决方案,请随时向我展示。

【问题讨论】:

  • "当移除这个容器中间的一个元素时,它的位置会是空的,不会发生其他事情。"请定义empty .
  • 使用迭代器删除某些东西——这个迭代器肯定会失效
  • 所以你想要stable_vector in boost这样的东西?
  • @πάνταῥεῖ 我的意思是这个位置的内存仍然在容器内部(拥有),但它不包含可以访问的元素。
  • stable_vector 的工作方式如下:它有一个指向单独分配的数据节点的指针向量。除了数据元素之外,每个节点都有一个反向指针,该指针指向指向该节点的向量内的指针。迭代器指向这些节点。当一个元素被插入或删除时,它之后的节点中的所有后向指针都会被调整。我太快了,无法宣布这样的事情是不可能的;我道歉。

标签: c++ c++11 containers


【解决方案1】:

要求 1: 插入(插入或推回)和一些删除(删除,而不仅仅是最后一个元素)

  • 符合条件的候选人:dequeforward_listlistmapmulti_mapsetmultisetunordered_mapunordered_multimap0、unordered_multimap0、@3 987654331@和vector

  • 被淘汰的候选人:array(没有insertpush_back)、queuepriority_queuestack(没有erase,只有pop

要求2:在调用这两个方法时不会使迭代器和指针失效

  • 满足要求 1 的符合条件的候选人:forward_listlistmapmulti_mapsetmultiset
  • 擦除时消除:deque(迭代器仅在擦除第一个元素时保持有效)和vector(擦除开始后的所有元素)
  • 插入时消除:dequeue(在大多数情况下)、unordered_mapunordered_multimapunordered_setunordered_multiset(以防增长需要重新散列)和 vector(以防增长需要重新分配)

要求 3: 外部指针应保持有效

与要求 2 的结果大致相同。但是 unordered_mapunordered_multimapunordered_setunordered_multiset 将满足此要求,因为对元素的引用仍然有效。

要求 4: 随机访问元素

  • 满足要求 1 和 2 的合格候选人:mapmultimap
  • 几乎符合条件的候选人:setmultiset 没有随机访问,但可以使用成员 find() (O(logn)) 满足它
  • 不符合:列表(尽管算法find() 可以在 O(n) 中提供解决方法)。

问题 1 的答案: setlist 哪个更好?

这取决于您的其他要求。在一个集合中,每个值只能存储一次。如果您的元素都是唯一的,请选择集合。如果不是,您最好选择列表或多组。

我不知道您要存储的元素,但整个元素是搜索参数吗?还是有钥匙?在后一种情况下,您真的会选择地图。

问题 2 的答案:替代容器怎么样?

我不会选择双端队列作为您的替代方案。

如果您可以预见元素的最大数量,您可以简单地保留足够的容量以避免重新分配。 (满足要求 1、3 和 4)。 如果你有一个“空元素”来表示孔,那么你也可以满足要求 2。在最坏的情况下,你可以选择一个向量来排列你的元素,如果它是有效的,你可以选择一个指示符。

如果无法确定这样的最大值,我宁愿选择map,它被证明是灵活的并且可以满足您的所有要求。

【讨论】:

    猜你喜欢
    • 2015-12-23
    • 1970-01-01
    • 2014-12-05
    • 2017-10-05
    • 2017-04-11
    • 2012-07-11
    相关资源
    最近更新 更多