5

我知道以下代码不正确,对于 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 这似乎说明了我可以在不使迭代器无效的情况下擦除。但是我不确定是否因为我删除了一个元素,我应该在迭代期间访问的另一个元素可以移动到当前迭代器的位置之前并且永远不会被访问(换句话说,通过在迭代期间擦除一些元素,我仍然确定要遍历所有元素吗?)。

谢谢!

4

2 回答 2

7

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

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

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

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

于 2012-10-22T09:10:35.790 回答
3

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

实际的文字是:

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

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

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

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

于 2012-10-22T09:06:10.830 回答