// erasing from map
#include <iostream>
#include <map>
using namespace std;
int main ()
{
map<char,int> mymap;
map<char,int>::iterator it(mymap.begin());
// insert some values:
mymap['a']=10;
mymap['b']=20;
mymap['c']=30;
mymap['d']=40;
mymap['e']=50;
mymap['f']=60;
it=mymap.find('a');
mymap.erase (it); // erasing by iterator
// show content:
for (; it != mymap.end(); it++ )
cout << (*it).first << " => " << (*it).second << endl;
return 0;
}
Pourquoi cela donne-t-il une sortie comme
a => 10
b => 20
c => 30
d => 40
e => 50
f => 60
de toute façon, "a => 10"
ne devrait pas être supprimé, mais si je déclare it = mymap.begin()
dans la boucle for, tout est parfait. Pourquoi?
programme adapté de: http://www.cplusplus.com/reference/stl/map/erase/
Effacer un élément de map
invalide les itérateurs pointant sur cet élément (une fois que tout cet élément a été supprimé). Vous ne devriez pas réutiliser cet itérateur.
Depuis C++ 11, erase()
renvoie un nouvel itérateur pointant sur l'élément suivant, qui peut être utilisé pour continuer à itérer:
it = mymap.begin();
while (it != mymap.end()) {
if (something)
it = mymap.erase(it);
else
it++;
}
Avant C++ 11, vous deviez faire avancer l'itérateur manuellement vers l'élément suivant avant que la suppression ait lieu, par exemple comme ceci:
mymap.erase(it++);
Cela fonctionne car l'effet secondaire de it++
après l'incrémentation se produit avant que erase()
ne supprime l'élément. Comme cela n’est peut-être pas immédiatement évident, la variante C++ 11 ci-dessus devrait être préférée.
L'appel de erase()
invalide l'itérateur. Dans ce cas, l'itérateur pointe la valeur résiduelle laissée dans la mémoire (mais ne vous fiez pas à ce comportement indéfini!). Réinitialisez l'itérateur avec it=mymap.begin()
avant la boucle pour obtenir les résultats souhaités.
Cette réponse montre comment effacer des éléments en effectuant une itération sur un std::map
:
for(map<T, S*>::iterator it = T2pS.begin(); it != T2pS.end(); T2pS.erase(it++)) {
// wilhelmtell in the comments is right: no need to check for NULL.
// delete of a NULL pointer is a no-op.
if(it->second != NULL) {
delete it->second;
it->second = NULL;
}
}
Cela a à voir avec la façon dont la map
est implémentée. Disons que c'est un arbre, comme:
class map_node {
char key;
int value;
map_node* next;
...
};
Lorsque vous erase()
l'itérateur, vous supprimez le nœud de l'arborescence et libérez son espace. Mais jusqu'à ce que cet emplacement de mémoire soit écrasé, le contenu du nœud est toujours en mémoire. C'est pourquoi vous pouvez obtenir non seulement la valeur, mais également l'élément suivant de l'arbre. Ainsi, votre résultat est tout à fait attendu.
it
n'est plus valide après mymap.erase(it)
. Cela signifie qu'il peut faire ce qu'il veut.
"it" pointe toujours au même endroit, effacer ne met pas à jour l'itérateur par lui-même, vous devez le faire en réinitialisant l'itérateur. En effet, "it" pointe sur l’ancien emplacement qui a été effacé du vecteur mais contient toujours les anciennes données.