IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SL & STL C++ Discussion :

Utilisation correcte des vectors et iterators


Sujet :

SL & STL C++

  1. #1
    Membre éprouvé
    Avatar de Ange_blond
    Homme Profil pro
    Ingénieur développement en 3D temps réel
    Inscrit en
    Mars 2007
    Messages
    902
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement en 3D temps réel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2007
    Messages : 902
    Points : 1 179
    Points
    1 179
    Par défaut Utilisation correcte des vectors et iterators
    Bonjour,

    Je me heurte à un petit soucis avec les Iterators sur std::vector<>.

    J'ai une méthode, chargée de trouver un element dans un vector, et de le supprimer du vector.

    Le trouver n'est pas un soucis, mais apres la suppression, l'iterator devient invalide, et provoque un crash. (sur l'operateur ++)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for(it = _mov1->getMeasureLineList()->begin() ; it != _mov1->getMeasureLineList()->end() ; it++)
    		if((*it) == this)
    		{
    			_mov1->getMeasureLineList()->erase(it);
    		}
    Si la liste ne comporte qu'un element par exemple, le crash est systématique.
    Pour le moment j'évite le soucis en ajoutant un "break" apres le erase, pour quitter la boucle dans faire le it++ si risqué.

    il semblerais que la méthode erase() ne prenne pas la peine de vérifier l'état de la liste et de l'itérateur et le retourne dans un état incertain...

    Vous feriez/faites comment vous pour faire ça proprement et avec un maximum de sécurité ?

    Merci.
    "le langage C permet de tout faire, y compris se tirer dans le pied. Le langage C++ permet de tout faire, y compris se tirer dans le pied - et réutiliser la balle"

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Erase, comme toutes les fonctions modifiant le nombre d'élément d'un vecteur, invalide tous les itérateurs sur ce vecteur. Par contre, il retourne un itérateur qui pointe sur l'élément juste après celui qu'on est en train d'enlever. A partir de là, il est possible de se débrouiller.

    A noter que si on veut enlever plusieurs valeurs d'un coup, il vaut mieux utiliser remove_if qui est plus performant.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre éprouvé
    Avatar de Ange_blond
    Homme Profil pro
    Ingénieur développement en 3D temps réel
    Inscrit en
    Mars 2007
    Messages
    902
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement en 3D temps réel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2007
    Messages : 902
    Points : 1 179
    Points
    1 179
    Par défaut
    Merci

    J'ai adapté donc en :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	for(it = _mov1->getMeasureLineList()->begin() ; it != _mov1->getMeasureLineList()->end() ; it++)
    		if((*it) == this)
    		{
    			it = _mov1->getMeasureLineList()->erase(it);
    			//break;
    		}
    Mais toujours le meme soucis.

    En effet, la doc stipule :
    Return value
    A random access iterator pointing to the new location of the element that followed the last element erased by the function call, which is the vector end if the operation erased the last element in the sequence.
    Mais malgré tout, toujours mon plantage sur l'iterator++ ...

    Je ne comprend pas vraiment pourquoi...
    "le langage C permet de tout faire, y compris se tirer dans le pied. Le langage C++ permet de tout faire, y compris se tirer dans le pied - et réutiliser la balle"

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Ton code va poser problème dans le sens où si tu as les éléments
    1 2 3 4 5
    Et que tu effaces 3, après it = _mov1->getMeasureLineList()->erase(it);
    it pointera sur 4, et après le ++it, il pointera sur 5. Donc tu auras sauté l'élément suivant celui effacé.

    Et si jamais l'élément effacé est le dernier, tu itéreras trop loin, ce qui peut causer un plantage.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Un code correct pour supprimer un élément d'un vecteur est présent dans la faq.

    Mais malgré tout, toujours mon plantage sur l'iterator++ ...
    ça vient peut être du fait que ton élément à supprimer est le dernier du vecteur. Dans ce cas erase renvoie end et it++ plante au tour de boucle suivant, vu que il est impossible d'incrémenter un itérateur au delà de end.

  6. #6
    Membre éprouvé
    Avatar de Ange_blond
    Homme Profil pro
    Ingénieur développement en 3D temps réel
    Inscrit en
    Mars 2007
    Messages
    902
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement en 3D temps réel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2007
    Messages : 902
    Points : 1 179
    Points
    1 179
    Par défaut
    Merci du coup de main, en effet j'ai raté le code dans la FAQ

    j'ai ajouté une instruction pour terminer plus vite la boucle ce qui au final donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    	for(it = _mov1->getMeasureLineList()->begin() ; it != _mov1->getMeasureLineList()->end() ; )
    	{
    		if((*it) == this)
    		{
    			_mov1->getMeasureLineList()->erase(it);
    			it = _mov1->getMeasureLineList()->end(); //end looping
    		}
    		else
    			++it;
    	}
    Merci encore.

    @++
    "le langage C permet de tout faire, y compris se tirer dans le pied. Le langage C++ permet de tout faire, y compris se tirer dans le pied - et réutiliser la balle"

  7. #7
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Y'a un gros soucis dans la doc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <vector>
    
    std::set<int> s;
    for (std::vector<int>::iterator it = s.begin(); it != s.end(); )
    {
        if (*it == 5)
            it = s.erase(it);
        else
            ++it;
    }
    Que vient faire le set ?

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par camboui Voir le message
    Que vient faire le set ?
    C'est en effet un erreur. Elle est déjà corrigée dans la prochaine version de la FAQ. Il faut que je trouve le temps d'avancer dessus et de la publier.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 21/02/2014, 11h29
  2. Utilisation avancée des iterators
    Par scheme dans le forum Langage
    Réponses: 7
    Dernier message: 04/02/2011, 19h13
  3. utilisation correcte des template variadiques C++11
    Par mangobango dans le forum C++
    Réponses: 12
    Dernier message: 14/05/2010, 23h17
  4. [JSP] utilisation dynamique des includes
    Par shinchun dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 24/05/2004, 15h28
  5. [ENCODAGE][JAVA]Afficher correctement des accents
    Par kornelius dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 17/02/2004, 16h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo