use*_*682 4 c++ containers dictionary iterator loops
我在循环通过地图时遇到问题(std :: map).
在我的循环中,有一个函数调用,有时(并不总是)擦除同一个映射的元素.使用此函数后,有一些代码使用这些映射信息作为输入.
在此功能擦除任何元素后,我没有任何问题,除了在地图的最后一个元素被删除的独特情况.
我的循环semms不明白地图的最后一个元素与它开始运行时的不一样,并且会尝试对不存在的元素进行操作,从而造成崩溃.
在我看来,对循环描述的myMap.end()调用无法使用地图的新end()更新自身.
代码的相关部分如下:
for(std::map<int, ConnectionInfo>::iterator kv = myMap.begin(); kv != myMap.end(); ++kv) {
int thisConnectionID=kv->first; //This is where I get garbage when the loop enters when it shouldnt;
ConnectionInfo currentConnectionInfo=kv->second; //This is where I get garbage when the loop enters when it shouldnt;
status=eraseSomeMapElementsIfNecessary(thisConnectionID,currentConnectionInfo.DownPacket); //this function might erase elements on myMap. This generates no problems afterwards, except when the end element of myMap is erased
... //Next parts of the code make no further usage of myMaps, so I just hid it not to pollute the code
}
Run Code Online (Sandbox Code Playgroud)
我的解释kv != myMap.end()是,无法理解内循环正在改变(擦除)myMap的最后一个元素(结束)?
在这种情况下,我该如何解决这个问题?
或者我的解释是错误的,解决方案与我之前所说的无关?
谢谢你的帮助!
迭代具有可能删除元素的地图时通常的习惯用法是:
for(auto it = map.begin(); it != map.end(); ) {
if ( *it == /*is to delete*/ ) {
it = map.erase(it);
}
else
++it;
}
Run Code Online (Sandbox Code Playgroud)
如果你的eraseSomeMapElementsIfNecessary可能会删除迭代的map中的一些随机值,那么这肯定会导致问题.如果元素,其it被引用得一干二净,就变成无效,然后递增it用++it也无效.
问题实际上只有it迭代器,如果eraseSomeMapElementsIfNecessary擦除它然后你使用它 - 你有未定义的行为(UB).因此解决方案是将当前迭代器传递给eraseSomeMapElementsIfNecessary,并从中返回下一个迭代:
it = eraseSomeMapElementsIfNecessary(it);
Run Code Online (Sandbox Code Playgroud)
我的示例中for循环的主体应该在eraseSomeMapElementsIfNecessary函数中.至少这是一个解决方案.