我想迭代一个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);
}
}
Run Code Online (Sandbox Code Playgroud)
除非删除第一个项目,否则迭代会起作用,然后抛出以下错误:
map/set iterator不可递增
removeFromMap为了正常工作,如何重写函数?代码应该适用于地图的各种键和值类型.
我正在使用C++ 11和Visual Studio 2013.
在进行擦除之前,需要增加迭代器.当你这样做时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;
}
}
Run Code Online (Sandbox Code Playgroud)
应用于参数it内部的后增量map.erase()将确保it在擦除项之后保持有效,方法是将迭代器递增以指向擦除之前的地图中的下一个项目.
map.erase(it++);
Run Code Online (Sandbox Code Playgroud)
......在功能上等同于......
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.
Run Code Online (Sandbox Code Playgroud)
正如@imbtfab在评论中指出的那样,你也可以it = map.erase(it)在C++ 11中做同样的事情,而不需要后递增.
另请注意,for由于我们手动控制迭代器,因此循环现在已更改为while循环.
另外,如果您希望尽可能使removeFromMap函数尽可能通用,则应考虑使用模板参数并直接传递迭代器,而不是传递对多图的引用.这将允许您使用任何地图样式的容器类型,而不是强制使用multimap.
例如
template <typename Iterator>
void removeFromMap(Iterator it, const Iterator &end){
...
}
Run Code Online (Sandbox Code Playgroud)
这也是标准C++ <algorithm>函数如何做到这一点(例如std::sort(...)).
| 归档时间: |
|
| 查看次数: |
1485 次 |
| 最近记录: |