是否有标准容器允许插入元素而不会使迭代器失效?

时间:2012-02-10 16:07:08

标签: c++ stl containers

在C ++中,是否存在允许我在以下for循环中向其添加元素的数据结构?

(我使用list作为例子,因为这是我到目前为止所尝试过的。)

list<Elem> elems;
// fill elems with some Elems;

for(list<Elem>::iterator it=elems.begin(); it!=elems.end();) {

    // ...

    if(condition)
        it = elems.erase(it);
    else {
        Elem elem;
        it = elems.push_back(elem);
    }
}

PS:这是Deleting elements from a vector

的后续问题

4 个答案:

答案 0 :(得分:3)

This answer on StackOverflow概述了所有标准容器的行为。

在插入或擦除时不会使迭代器无效的容器是listsetmultisetmapmultimap。当然这不包括被删除的迭代器。

答案 1 :(得分:1)

是的,list允许你这样做..正如我在其他答案的评论中所说的那样......

答案 2 :(得分:1)

根据请求编写此内容。

  

PS:这是从矢量中删除元素的后续问题

这是你提问的一个令人不安的模式。

说真的,在迭代容器时修改容器是坏事。很难做对。在性能方面,它通常不会为您节省太多。很少(除了在有限的情况下,有一个标准库算法完全适合您的需求)更容易表达。如果你做错了,它的性能会非常昂贵。如果你做错了,那么在程序正确性方面可能会非常昂贵,这比其他任何东西都重要得多。

如果涉及线程,则会出现指数恶化。 Java有一个专用的异常类型,专门针对某些可能在您尝试时出错的事情。在C ++中你不是那么幸运;类似的问题可能无法检测到。

只需编写产生最终结果的代码,然后替换原始容器。唯一可以真正减缓这种情况的是“实例复制成本很高”,在这种情况下,您应该已经使用了一层间接来处理问题(假设它真的很重要)。

list<Elem> original;
// fill elems with some Elems;
list<Elem> modified;
for (
    list<Elem>::iterator it = original.begin(), end = original.end();
    it != end; ++it
) {
    if (something()) {
        modified.push_back(*it);
    } else if (something_else()) {
        modified.push_back(Elem()); // for example
    }
    // else, 'erase' the element by just not putting anything into 'modified'
    // Or we could do whatever other combination of things,
    // maybe insert more than one
}
std::swap(original, modified);

答案 3 :(得分:0)

several containers支持插入而不会使迭代器失效。在你的代码中,你有正确的删除案例,但我相信你过度思考插入案例。试试这个:

else {
    Elem elem;
    elems.push_back(elems);
    ++it;
}

您在给定示例中使用了list,因此您知道push_back来电不会使it无效。因此,您可以简单地增加它以到达下一个元素。您只需要在removing elements时小心,因为您无法递增指向不再存在的位置的迭代器。