Ce qui arrive à une STL itérateur après l'effacement de VS, UNIX/Linux?
Veuillez considérez le scénario suivant:
map(T,S*) & GetMap(); //Forward decleration
map(T, S*) T2pS = GetMap();
for(map(T, S*)::iterator it = T2pS.begin(); it != T2pS.end(); ++it)
{
if(it->second != NULL)
{
delete it->second;
it->second = NULL;
}
T2pS.erase(it);
//In VS2005, after the erase, we will crash on the ++it of the for loop.
//In UNIX, Linux, this doesn't crash.
}//for
Il me semble que dans VS2005, après les "effacer", l'itérateur sera égal à la fin(), d'où le crash lors de la tentative de l'incrémenter.
Y a t il vraiment des différences entre les compilateurs dans le comportement présenté ici?
Si oui, quel sera l'itérateur après les "effacer" l'égalité dans UNIX/Linux?
Merci...
Demandé et répondu: stackoverflow.com/questions/263945/...
OriginalL'auteur Gal Goldman | 2009-01-11
Vous devez vous connecter pour publier un commentaire.
Oui, si vous effacez un itérateur, qui itérateur obtient un soi-disant valeur singulière, ce qui signifie qu'il n'appartient pas à un conteneur plus. Vous ne pouvez pas incrémenter, décrémenter ou lecture/écriture à elle. La bonne façon de le faire que la boucle est:
Pour les conteneurs qui pourrait invalider d'autres itérateurs lorsque vous effacez un itérateur,
erase
retourne le prochain valide itérateur. Alors vous le faites avecComment ça marche pour
std::vector
etstd::deque
, mais pas pourstd::map
oustd::set
.Ok, je vais le corriger parce que vous avez tort 😉 erase(it++) l'argument est évalué avant de l'effacer est appelé, il va être (bien) incrémenté, c'est précédentes (unincremented), la valeur renvoyée pour effacer et que l'on devient invalide, mais il a lui-même déjà les points à l'élément suivant.
Je vois votre point de vue. Merci pour l'entrée
La suppression d'un pointeur null est un noop. Il n'est pas nécessaire de vérifier la valeur null.
vous pouvez mentionner que std::list ne pas invalider toute itérateur autres que l'itérateur(s) pointant vers la effacées élément(s), lors de l'appel du membre effacer() fonction.
OriginalL'auteur Johannes Schaub - litb
Après l'appel de
erase
sur un itérateur dans unstd::map
, il est invalidé. Cela signifie que vous ne pouvez pas l'utiliser. D'essayer de l'utiliser (par exemple, par incrémentation) n'est pas valide et peut causer à autre chose (y compris un crash). Pour unstd::map
, appelanterase
sur un itérateur n'invalide pas les autres itérateur (par exemple) après cet appel, (tant queit
n'était pasT2pS.end()
), il sera valable:Bien sûr, si vous utilisez cette méthode, vous ne voulez pas inconditionnellement incrément
it
dans la boucle for.Pour cet exemple, cependant, pourquoi s'embêter à effacer dans la boucle for? Pourquoi ne pas simplement appeler T2pS.clear() à la fin de la boucle.
D'autre part, il semble que vous avez un pointeur brut " sur la droite de la carte, mais la carte semble propre de la pointe de l'objet. Dans ce cas, pourquoi ne pas faire la chose sur la droite de la carte, une sorte de pointeur intelligent, comme std::tr1::shared_ptr?
[D'ailleurs, je ne vois pas de paramètres de modèle pour
map
. Avez-vous typedef ed spécifique de l'instanciation destd::map
commemap
dans l'espace de noms local?]OriginalL'auteur CB Bailey
Voir ce:
Aha! vecteur::erase(iterator) renvoie un autre itérateur, alors que map::erase(iterator) ne fonctionne pas. L'OP a discuté des cartes, mais c'est une information utile aussi.
Dans Visual C++, map::erase(iterator) retourne un itérateur, mais ce n'est pas une procédure standard.
Voir: sgi.com/tech/stl/Map.html la Recherche pour les effacer(). Il renvoie void.
OriginalL'auteur orip
Je pense que si vous modifiez la collection invalider votre itérateur. Vous ne pouvez pas compter sur le comportement, comme vous l'avez trouvé.
La droite. Je suppose que ce n'était pas très clair.
OriginalL'auteur Sam Hoice