我使用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
}
答案 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));
与其他例子相同。顺便说一句,这就是为什么通常使用前缀++和迭代器的原因;复制操作是额外的开销,你通常不需要它。