std :: map :: erase(it ++)是否维护一个指向地图中下一个元素的有效迭代器?

时间:2014-04-29 01:09:01

标签: c++ c++11 stl stdmap

我使用Xcode和C ++ 11作为std :: map。我的地图中的某些元素有一个标记,表示需要将其删除。

我想遍历地图,在O(n)时间内删除标记的元素。对erase的调用不会返回迭代器。我已经看到了某种擦除(it ++)实现,但我没有证据表明这样的调用可以工作,因为迭代器在擦除操作之后但在增量操作之前将变为无效。

我目前的代码似乎效率低下。

for(auto it = myMap.begin(); it != myMap.end(); ++it)
{
    delete *it;
    myMap.erase(it);
    it = myMap.begin(); //how can I avoid iterating through the map again
}

2 个答案:

答案 0 :(得分:4)

std::map::erase()传递迭代器时,它会将迭代器返回到被删除元素后面的下一个元素。这允许您继续迭代而无需重新开始。

试试这个:

auto it = myMap.begin();
while (it != myMap.end())
{
    if (it->flagged)
    {
        delete *it;
        it = myMap.erase(it);
    }
    else
        ++it;
}

答案 1 :(得分:3)

来自在线文档:

"引用该函数删除的元素的迭代器,指针和引用无效。所有其他迭代器,指针和引用都保持其有效性。"

所以也许这个:

for(auto it = myMap.begin(); it != myMap.end();)
{
    auto itPrev = it;
    ++it;

    if(shouldBeDeleted(*itPrev))
       myMap.erase(itPrev);
}

编辑:你提到的erase(it++)想法实际上没问题,因为在调用erase()之前会发生增量(并返回旧的预增量值的副本)。它实际上相当于:

template<typename IteratorT>
IteratorT PostIncrement(IteratorT& it)
{
   auto copy = it;
   ++it;
   return copy;
}

for(auto it = myMap.begin(); it != myMap.end();)
   myMap.erase(PostIncrement(it));

与其他例子相同。顺便说一句,这就是为什么通常使用前缀++和迭代器的原因;复制操作是额外的开销,你通常不需要它。