Qu'advient-il si vous appelez effacer() sur un élément de la carte lors de l'itération de commencer à la fin?
Dans le code suivant, je boucle sur une carte et de tester si un élément doit être effacé. Est-il sûr d'effacer l'élément et de garder l'itération ou dois-je chercher les clés dans un autre récipient et faire une seconde boucle pour appeler l'effacer()?
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);
}
}
Mise à JOUR: bien sûr, j'ai ensuite lisez cette question qui je ne pense pas que se soit lié mais répond à ma question.
- Veuillez noter en question que
std::remove_if
ne fonctionne pas avecstd:map
Vous devez vous connecter pour publier un commentaire.
C++11
Cela a été corrigé dans C++11 (ou d'effacement a été améliorée/mis en cohérence à travers tous les types de conteneurs).
La méthode d'effacement maintenant retourne l'itérateur suivant.
C++03
L'effacement d'éléments dans une carte n'a pas pour effet d'invalider toutes les itérateurs.
(hormis les itérateurs sur l'élément qui a été supprimé)
En fait l'insertion ou la suppression n'a pas pour effet d'invalider toutes les itérateurs:
Aussi voir cette réponse:
Marque Rançon Technique
Mais vous avez besoin de mettre à jour votre code:
Dans votre code, vous incrément pm_it après l'appel de l'effacer. À ce stade, il est trop tard et il est déjà invalidé.
pm_it++
garanti pour être exécuté avant que la fonction est entré?delete_this_id
désigne le dernier élément. Ne serait-il pas préférable d'utiliserpm_it = port_map.erase(pm_it)
?id
pas un itérateur. La boucle n'est pas entré pour laend()
itérateur de sorte que ne s'applique pas. Si vous voulez diredelete_this_id
désigne le dernier élément de la carte. Ensuite, il faudra encore travailler.pm_it++
est appelée avant laerase()
est appelé. L'incrémentation de la variable d'itération à partir du dernier élément deend()
est parfaitement valide. Le résultat de laoperator++()
renvoie la valeur d'origine (avant l'incrément) et est donc une valeur valide pour être passé àerase()
.map
. Mon test indique qu'il va échouer si le dernier élément est effacé et si le conteneur est unvector
parce que l'un des effets secondaires deerase
est que la valeur retournée parend()
changements. L'incrémentation de la variable d'itération danserase(...)
, par opposition à l'aidepm_it = port_map.erase(pm_it)
les causes de l'itérateur pour être valide. Désolé pour la confusion.Sequence
conteneurs. La propriété spéciale deAssociative
conteneurs est que les itérateurs ne sont pas invalidées par les effacer ou les insérer (à moins que ce point de l'élément qui a été effacé). Vecteur et de les effacer avec les itérateurs est couvert en détail dans la question stackoverflow.com/a/3938847/14065pm_it = port_map.erase(pm_it);
comme cela garantit que pm_it devient la prochaine valide itérateur ou port_map::fin si le dernier élément est effacé. Mais dans le code ci-dessus par @LokiAstari une fois que vous effectuezport_map.erase(pm_it)
pm_it devient un pointeur non valide et l'exploitation, par la suite, peut provoquer le programme se terminer.port_map.erase(pm_it)
dans le code ci-dessus. Nous avons faites l'appoint:port_map.erase(pm_it++)
pour le faire fonctionner.Voici comment j'ai fait ...
C'est comment j'allais le faire, environ:
Il y a quelque chose d'étrange à propos de
mais je viens de copier à partir de votre code d'exemple.