如果在从开始到结束的迭代过程中调用地图元素上的erase()会发生什么?

在下面的代码中,我通过一个映射循环,testing一个元素是否需要被擦除。 清除元素并继续迭代是否安全?还是需要将密钥收集到另一个容器中,然后执行第二个循环来调用erase()?

map<string, SerialdMsg::SerialFunction_t>::iterator pm_it; for (pm_it = port_map.begin(); pm_it != port_map.end(); pm_it++) { if (pm_it->second == delete_this_id) { port_map.erase(pm_it->first); } } 

更新:当然,我然后读这个问题 ,我不认为会相关,但回答我的问题。

C ++ 11

这已经在C ++ 11中得到修复(或者擦除已经在所有容器types上得到改进/保持一致)。
擦除方法现在返回下一个迭代器。

 auto pm_it = port_map.begin(); while(pm_it != port_map.end()) { if (pm_it->second == delete_this_id) { pm_it = port_map.erase(pm_it); } else { ++pm_it; } } 

C ++ 03

擦除地图中的元素不会使任何迭代器失效。
(除了被删除的元素上的迭代器)

实际上插入或删除不会使任何迭代器失效:

也看到这个答案:
Mark Ransom技术

但是你确实需要更新你的代码:
在你的代码中你调用擦除后递增pm_it。 此时已经太晚了,已经失效了。

 map<string, SerialdMsg::SerialFunction_t>::iterator pm_it = port_map.begin(); while(pm_it != port_map.end()) { if (pm_it->second == delete_this_id) { port_map.erase(pm_it++); // Use iterator. // Note the post increment. // Increments the iterator but returns the // original value for use by erase } else { ++pm_it; // Can use pre-increment in this case // To make sure you have the efficient version } } 

这是我怎么做的…

 typedef map<string, string> StringsMap; typedef StringsMap::iterator StrinsMapIterator; StringsMap m_TheMap; // Your map, fill it up with data bool IsTheOneToDelete(string str) { return true; // Add your deletion criteria logic here } void SelectiveDelete() { StringsMapIter itBegin = m_TheMap.begin(); StringsMapIter itEnd = m_TheMap.end(); StringsMapIter itTemp; while (itBegin != itEnd) { if (IsTheOneToDelete(itBegin->second)) // Criteria checking here { itTemp = itBegin; // Keep a reference to the iter ++itBegin; // Advance in the map m_TheMap.erase(itTemp); // Erase it !!! } else ++itBegin; // Just move on ... } } 

这是我将如何做,大约:

 bool is_remove( pair<string, SerialdMsg::SerialFunction_t> val ) { return val.second == delete_this_id; } map<string, SerialdMsg::SerialFunction_t>::iterator new_end = remove_if (port_map.begin( ), port_map.end( ), is_remove ); port_map.erase (new_end, port_map.end( ) ); 

有一些奇怪的东西

 val.second == delete_this_id 

但我只是从你的示例代码复制它。