Vous devez augmenter votre iterator avant que vous faites l'effacement. Lorsque vous faites map.erase(it);
l'itérateur it
devient invalide. Cependant, les autres itérateurs de la carte seront toujours valides. Par conséquent, vous pouvez résoudre ce problème en effectuant un post-augmentation de la iterator ...
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;
}
}
Le post-incrément appliqué à it
à l'intérieur des paramètres map.erase()
veillera à ce que it
reste valable après l'article est effacé par incrémenter l'itérateur pour pointer vers l'élément suivant sur la carte juste avant d'effacer.
map.erase(it++);
... est fonctionnellement équivalent à ...
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.
Comme @imbtfab souligne dans les commentaires, vous pouvez également utiliser it = map.erase(it)
pour faire la même chose en C++ 11 sans besoin de post-incrémentation.
Notez également que la boucle for
a maintenant été remplacée par une boucle while car nous contrôlons l'itérateur manuellement. De plus, si vous cherchez à rendre votre fonction removeFromMap
aussi générique que possible, vous devriez envisager d'utiliser des paramètres de modèle et de transmettre vos itérateurs directement, plutôt que de passer une référence à la multi-carte. Cela vous permettra d'utiliser n'importe quel type de conteneur de type carte, plutôt que de forcer l'insertion d'un multimap
.
par exemple.
template <typename Iterator>
void removeFromMap(Iterator it, const Iterator &end){
...
}
Voici comment les fonctions standard C++ <algorithm>
faire aussi (par exemple std::sort(...)
).
Normalement, on utilise la valeur de retour de map.erase (itérateur), puisqu'il renvoie l'itérateur à l'élément ou à la fin suivant, si c'était le dernier élément – AquilaRapax
@Erbureth Vous devriez ajouter cela comme réponse :-) –
@ KarlNicoll Cependant, après avoir creusé plus profondément, l'idiome Erase-remove n'est pas applicable sur 'std :: set',' std :: map' et les amis, car leur type de valeur n'est pas 'MoveAssignable'. Et je n'ai aucune idée de la façon de l'implémenter sur de tels conteneurs, car cela fonctionne en déplaçant des éléments. – Erbureth