【问题标题】:Consistency when removing items from boost multi-index using an iterator使用迭代器从提升多索引中删除项目时的一致性
【发布时间】:2012-10-22 09:00:39
【问题描述】:

我知道以下代码不正确,对于 std::vectors 和更普遍的所有 STL 容器:

std::vector<something>::iterator it = array.begin();
for(; it != array.end(); it++) {
   ...
   array.erase(it);
   ...
}

因为在擦除和元素之后需要更新迭代器。

我想知道提升多索引是否相同,例如以下内容是否正确:

my_index::iterator it = index.get<0>().begin();
for(; it != index.get<0>().end(); it++) {
   ...
   index.erase(it);
   ...
}

我想确保很好地理解文档的以下段落:http://www.boost.org/doc/libs/1_51_0/libs/multi_index/doc/tutorial/indices.html#guarantees 这似乎表明我可以在不使迭代器无效的情况下进行擦除。但是我不确定是否因为我删除了一个元素,我应该在迭代期间访问的另一个元素可以移动到当前迭代器的位置之前并且永远不会被访问(换句话说,通过在迭代期间擦除一些元素,我仍然确定要遍历所有元素吗?)。

谢谢!

【问题讨论】:

    标签: c++ boost iterator boost-multi-index


    【解决方案1】:

    您链接的段落仅适用于散列(无序)索引。它指出当插入新元素时,散列索引迭代器仍然有效。

    擦除时,对于有序索引,您始终可以通过使用来自erase 的返回值来保证完全迭代:

    for (; it != index.get<0>().end(); ) {
        if (...) it = index.erase(it);
        else ++it;
    }
    

    这也适用于散列(无序)索引,因为迭代顺序在擦除元素上是稳定的。

    【讨论】:

      【解决方案2】:

      不,您的操作在提升索引中无效。从集合中删除的迭代器永远不会保持有效,如果您将它们存储在某个地方,那么可以保持有效的是集合中的其他迭代器。

      实际文字是:

      保证迭代器有效性和异常安全

      由于 Boost.MultiIndex 框架施加的内部约束,散列 索引提供迭代器有效性和异常安全性的保证 实际上比 C++ 标准库要求的要强 关于无序关联的技术报告 (TR1) 容器:

      在任何情况下,迭代器的有效性在插入或 重新散列:TR1 允许在重新散列时迭代器失效 (隐式或显式)执行。擦除元素或范围 通过迭代器的元素永远不会抛出,因为内部哈希 实际上并未调用函数和相等谓词对象。 rehash 无条件提供强大的异常安全保障。

      TR1 仅在内部散列函数和相等时才保证它 谓词对象不抛出。有点令人惊讶的结果是 符合 TR1 的无序关联容器可能会擦除 如果在重新散列期间抛出异常,则元素!一般来说, 这些更强的保证有利于用户的方便, 特别是指迭代器稳定性。 A(希望 最小)性能下降可能会导致这些 不过是商品。

      【讨论】:

      • 这是否意味着如果我创建原始迭代器的副本,该副本仍然有效?就像我做迭代器 it2 = it; index.erase(它);它=它2;它会工作吗?
      • 不,无论如何您都在“擦除”副本,您可以假设擦除按值获取其参数。您应该使用始终保证有效的 remove_if 算法。
      猜你喜欢
      • 1970-01-01
      • 2013-10-05
      • 1970-01-01
      • 2021-12-18
      • 2021-11-08
      • 2014-10-26
      相关资源
      最近更新 更多