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 :

Vider une std::map de pointeur


Sujet :

SL & STL C++

  1. #1
    Membre éprouvé
    Avatar de Zenol
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 812
    Points : 1 054
    Points
    1 054
    Par défaut Vider une std::map de pointeur
    Bonjour,
    Je cherche a suprimer tous les pointeurs qui figurent dans une std::map<int, SDL_Surface*>, et j'ai tenter d'utiliser ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for(TListSurface::iterator i = ListSurface.begin(); i != ListSurface.begin(); ++i)
    {
      SDL_FreeSurface((*i).second);
      ListSurface.erase(i);
    }
    Mais cela ne fonctione pas, et provoque un plantage a la fermeture de mon aplication, quand les elements doivent êtrent détruit(Joli message de window : "****.exe a rencontrer un problème et doit fermer. Nous vous prions de ...). Pouriez vous m'exepliquer pourquoi et m'indiquer la marche a suivre?

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Quand tu détruit un element d'une liste, tu invalides tous les itérateurs qui pointent sur cet élément. En d'autre terme, après ton erase, i est dans les choux et donc l'incrémentation dans la boucle (++i) ne rime à rien.
    Le truc c'est d'incrémenter l'itérateur avant de détuire l'élément.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for(TListSurface::iterator i = ListSurface.begin(); i != ListSurface.begin(); /*EMPTY*/)
    {
      SDL_FreeSurface((*i).second);
      ListSurface.erase(i++);
    }
    Note que ceci fonctionne aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for(TListSurface::iterator i = ListSurface.begin(); i != ListSurface.begin(); ++i)
    {
      SDL_FreeSurface((*i).second);
    }
    ListSurface.clear();
    Ou encore, plus tordu mais sans boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    struct FreeSurface
    {
      void operator()(TListSurface::value_type aPair)
      {
        SDL_FreeSurface(aPair.second);
      }
    };
     
    for_each(ListSurface.begin(), ListSurface.end(), FreeSurface());
    ListSurface.clear();

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Ah, au fait, je préfère bien entendu la dernière solution ;-)

  4. #4
    Membre éprouvé
    Avatar de Zenol
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 812
    Points : 1 054
    Points
    1 054
    Par défaut
    Moi la deuxième(valide), car je me passe de déclarer encore une structure(je suis dans une classe qui comprend pas male de structure alors si je peut eviter d'en utiliser une) et je me passe d'#include <algoritme>
    Par contre, je n' ai pas comprit, quand je détruit ma surface,, i doit pointer un élément plus loin? Pourquoi?

    En tout cas, merci de ton aide.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Citation Envoyé par JC_Master
    Moi la deuxième(valide), car je me passe de déclarer encore une structure(je suis dans une classe qui comprend pas male de structure alors si je peut eviter d'en utiliser une) et je me passe d'#include <algoritme>
    Par contre, je n' ai pas comprit, quand je détruit ma surface,, i doit pointer un élément plus loin? Pourquoi?
    Détruire un élément d'une liste INVALIDE tout les itérateurs qui pointent dessus, c'est gravé dans le marbre (enfin dans le standard).
    Executer l'instruction ci dessous rend l'itérateur it est inutilisable.
    Incrémenter it à la suite de cette instruction n'a aucun sens, et peut même amener un plantage.

    En revanche si tu suit pas à pas le déroulement de l'instruction suivante tu évites le travers précédent.
    1/ une variable temporaire est crée, elle contient une copie de l'itérateur it
    2/ it est incrémenté. Il pointe sur l'élément suivant dans la liste.
    3/ l'élément de la liste pointé par le temporaire est supprimé de la liste
    => Tous les itérateurs qui pointaient sur cet éléments deviennent invalides. Mais pas it
    puisqu'il pointe sur l'élément suivant.

    Les limites de validités des iterateurs ainsi que toutes les conséquences des fonctions membres sont standard et mentionnées dans la doc STL.


    NOTA: si tu passes par un foncteur, il n'y a aucun besoin de déclarer la structure à l'intérieur de la classe. La meilleure place, à mon sens est dans le namespace sans nom dans le fichier d'imlémentation de la classe.

  6. #6
    Membre éprouvé
    Avatar de Zenol
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 812
    Points : 1 054
    Points
    1 054
    Par défaut
    Saufe que la je n'ai pas mit de namespace ^^
    Mais sa ira comme sa. Au pire je peut toujours changer 2-3lignes de code.

  7. #7
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Août 2003
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2003
    Messages : 66
    Points : 51
    Points
    51
    Par défaut
    Petite remarque messieur..... on ne devrait pas utiliser *.end() comme 2ieme arg dans la boucle for ?? J"ai peut-etre manque une subtilite

    sinon il aurait aussi (jamais esseye, ca vient de me passer par l'esprit):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    for(TListSurface::iterator i = ListSurface.begin(); i != ListSurface.end(); i = ListSurface.begin())
    {
      SDL_FreeSurface((*i).second);
      ListSurface.erase(i);
    }
    Personnellement, j'aime bien les 2 methodes ennonce par VoidSeer

  8. #8
    Membre averti Avatar de Rafy
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 415
    Points : 417
    Points
    417
    Par défaut
    Normalement erase retourne un itérateur valide donc si tu code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    for (TListSurface::iterator i = ListSurface.begin(); i != ListSurface.end();)
    {
      SDL_FreeSurface((*i).second); 
      i = ListSurface.erase(i);
    }
    Ca marche aussi... eheheh encore moins de modifs

  9. #9
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920

  10. #10
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Y'a pas moyen de faire une boucle pour supprimer la surface puis faire un clear sur la map, c'est pas plus propre ?

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Citation Envoyé par Miles
    Y'a pas moyen de faire une boucle pour supprimer la surface puis faire un clear sur la map, c'est pas plus propre ?
    C'est la 2e des solutions que j'ai proposé (cf. plus haut)

  12. #12
    Membre averti
    Avatar de bigquick
    Profil pro
    Inscrit en
    Août 2002
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 356
    Points : 353
    Points
    353
    Par défaut
    Comme ca ?
    Citation Envoyé par VoidSeer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for(TListSurface::iterator i = ListSurface.begin(); i != ListSurface.begin(); ++i)
    {
       SDL_FreeSurface((*i).second);
    }
    ListSurface.clear();
    edit: ah, j'ai été doublé

  13. #13
    Membre éprouvé
    Avatar de Zenol
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 812
    Points : 1 054
    Points
    1 054
    Par défaut
    Merci loulou, j'avais male lut la FAQ, je navais pas vu it = s.erase(it);

  14. #14
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par VoidSeer
    Citation Envoyé par Miles
    Y'a pas moyen de faire une boucle pour supprimer la surface puis faire un clear sur la map, c'est pas plus propre ?
    C'est la 2e des solutions que j'ai proposé (cf. plus haut)
    Oups, pardon... J'ai en ce moment des petits problèmes qui m'empêchent de voir ce qu'il y a entre les balises code

  15. #15
    Membre éprouvé
    Avatar de Zenol
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 812
    Points : 1 054
    Points
    1 054
    Par défaut
    Ereur de compilation quand j'utilise it = s.erase(it); si it est un map<int, SDL_Surface*>::iterator ...

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 17/01/2009, 13h10
  2. Problème de fonction "const" avec une std::map
    Par Clad3 dans le forum SL & STL
    Réponses: 3
    Dernier message: 02/01/2007, 12h38
  3. Réponses: 9
    Dernier message: 16/10/2006, 16h35
  4. prédicat pour min_element d'une std::map
    Par Kurisu dans le forum SL & STL
    Réponses: 6
    Dernier message: 11/09/2006, 19h27
  5. Libérer des pointeurs dans une std::map
    Par GaldorSP dans le forum SL & STL
    Réponses: 2
    Dernier message: 09/07/2005, 14h42

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