我想迭代std::multimap
中的所有项目(所有键的所有值),并删除满足某些条件的所有条目:
#include <map>
typedef int KEY_TYPE;
typedef int VAL_TYPE;
bool shouldRemove(const KEY_TYPE&, const VAL_TYPE&);
void removeFromMap(std::multimap<KEY_TYPE,VAL_TYPE>& map){
for (auto it = map.begin(); it != map.end(); it++){
if (shouldRemove(it->first,it->second))
map.erase(it);
}
}
除非第一项被删除,否则迭代会起作用,然后抛出以下错误:
map / set iterator not incrementable
为了正常工作,如何重写removeFromMap
函数?代码应该适用于地图的各种键和值类型。
我正在使用C ++ 11和Visual Studio 2013。
答案 0 :(得分:5)
在执行擦除之前,需要递增迭代器。执行map.erase(it);
时,迭代器it
将变为无效。但是,地图中的其他迭代器仍然有效。因此,您可以通过在迭代器上进行后递增来解决此问题...
auto it = map.begin();
const auto end = map.end();
while (it != end)
{
if (shouldRemove(it->first,it->second))
{
map.erase(it++);
// ^^ Note the increment here.
}
else
{
++it;
}
}
在it
参数中应用map.erase()
的后增量将通过递增迭代器以指向地图中的下一个项目来确保it
在项目被删除后仍然有效就在擦除之前。
map.erase(it++);
......在功能上等同于......
auto toEraseIterator = it; // Remember the iterator to the item we want to erase.
++it; // Move to the next item in the map.
map.erase(toEraseIterator); // Erase the item.
正如@imbtfab在评论中指出的那样,你也可以使用it = map.erase(it)
在C ++ 11中做同样的事情而不需要后递增。
另请注意,for
循环现已更改为while循环,因为我们手动控制迭代器。
此外,如果您希望尽可能使removeFromMap
函数成为通用函数,则应考虑使用模板参数并直接传递迭代器,而不是传递对多地图的引用。这将允许您使用任何地图样式的容器类型,而不是强制使用multimap
。
e.g。
template <typename Iterator>
void removeFromMap(Iterator it, const Iterator &end){
...
}
标准C ++ <algorithm>
函数也是这样做的(例如std::sort(...)
)。