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 :

suppression d'un pointeur sur un objet dans un vector


Sujet :

SL & STL C++

  1. #1
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut suppression d'un pointeur sur un objet dans un vector
    Bonjour,

    J'ai bien lu la FAQ sur les vector, j'ai aussi lu ici que
    This effectively reduces the vector size by the number of elements removed, calling each element's destructor before.
    mais mon problème c'est surtout : Est-ce que le erase détruit bien l'objet, et si non quand dois-je le détruire ?

    Je viens d'essayer avant, et c'est la cata (ca me parait logique).
    Je n'ai pas essayé après pour le moment, car j'affiche le contenu de mon itérateur et il n'est plus le même après le erase :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    bool GUI_Container::Remove (std::string Name)
    {
        //Un itérateur
        std::vector<GUI_Container*>::iterator i;
        //Qui passe par tous les enfants de mon conteneur
        for (i=m_childs.begin();i<m_childs.end();i++)
        {
            //Si on trouve le bon enfant
            if ((*i)->m_name == Name)
            {
                std::cout<<"Avant :"<<(*i)<<std::endl;
                //On supprime du vecteur le pointeur sur l'enfant
                m_childs.erase(i);
                std::cout<<"Après :"<<(*i)<<std::endl;
                //Puis on sort
                return (true);
            }
        }
        //Enfant non trouvé
        return (false);
    }
    Et ca affiche :
    Construction du conteneur Root
    Construction du conteneur a
    Construction du conteneur b
    Root contient : 0
    Ajout de a
    Root contient : 1
    Ajout de b
    Root contient : 2
    On retire a
    Avant :0x22fc40
    Erase ici
    Après :0x22fc10
    Root contient : 1
    On retire b
    Avant :0x22fc10
    Erase ici
    Après :0x22fc10
    Root contient : 0
    Destruction du conteneur b
    Destruction du conteneur a
    Destruction du conteneur Root
    Et là, on voit qu'il détruit les objets à la fin du programme, et pas lors du erase, ce que je souhaite.

  2. #2
    Membre éprouvé
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Points : 1 067
    Points
    1 067
    Par défaut
    Il détruit bien les objets, sauf que ton vector contient des pointeurs! Il supprime alors bien les pointeurs, mais pas les objets pointés. Tu dois prévoir une libération propre de l'espace pointé.

    NB: après un erase(), l'iterator n'est plus valide, il faut le réassigner soit avec celui renvoyé (premier élément après celui effacé), soit avec begin(), end(), ....

  3. #3
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut
    Citation Envoyé par spoutspout Voir le message
    Il détruit bien les objets, sauf que ton vector contient des pointeurs! Il supprime alors bien les pointeurs, mais pas les objets pointés. Tu dois prévoir une libération propre de l'espace pointé.
    Ok, mais je fais comment ?

    Je peux copier le pointeur avant le erase, faire l'erase, puis appeler le destructeur via le premier pointeur ?

    Citation Envoyé par spoutspout Voir le message
    NB: après un erase(), l'iterator n'est plus valide, il faut le réassigner soit avec celui renvoyé (premier élément après celui effacé), soit avec begin(), end(), ....
    Ok, on est d'accord la-dessus, c'est bien ce que m'affiche le programme : Dans le premier cas, il pointe tout de suite ailleurs, dans le deuxième, il conserve la valeur, mais il n'est pas considéré comme valide pour autant. Je ne peux donc pas le détruire après. Donc première solution ci-dessus ?

  4. #4
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut
    Citation Envoyé par Mindiell Voir le message
    Je peux copier le pointeur avant le erase, faire l'erase, puis appeler le destructeur via le premier pointeur ?
    Ca marche pas

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut
    un truc comme ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    delete *i; // invalide le pointeur mais pas l'itérateur
    i = erase(i);
    La tu vas récupérer un itérateur valide mais attention tu ne peux pas l'utiliser tel quel pour continuer a parcourir ton vector car l'élément suivant l'élément supprimé sera sauté (a cause du ++i). Mais bon dans ton cas ca n'a pas d'importance car tu sors de la boucle des qu'un élément est supprimé.

    Après si tu ne veux pas invalider un pointeur directement dans ton vector (même si ce n'est que transitoire) tu peux faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    std::vector<GUI_Container*>::iterator tmp = i;
    i = erase(i);
    delete *tmp;

  6. #6
    Membre éprouvé
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Points : 1 067
    Points
    1 067
    Par défaut
    Citation Envoyé par Frifron Voir le message
    Après si tu ne veux pas invalider un pointeur directement dans ton vector (même si ce n'est que transitoire)
    Qu'est-ce qui l'empêche de faire ça? :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    delete (*it);
    my_vector.erase(it);

  7. #7
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut
    spoutspout> Je pense qu'il s'est trompé en retapant, je fais bien my_vector.erase (i)

    Ca marche, merci beaucoup !

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut
    Dans son cas rien, vu qu'il sors de la boucle directement. J'essayer juste de donner un cas plus général :

    Récupérer un itérateur valide apres un erase :
    Si il veut continuer sa boucle apres un erase.

    ne pas invalider un pointeur dans un conteneur :
    Si il y a du traitement entre les 2 instructions suceptibles de lancer une exception, il se retrouve avec un pointeur invalidé dans son conteneur

    Mais bon dans ce cas précis, ca ne change rien en effet. Attention toutefois a :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    m_childs.erase(i);
    std::cout<<"Après :"<<(*i)<<std::endl;
    comportement indeterminé si c'est le dernier élément qui est effacé.

  9. #9
    Membre éprouvé
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Points : 1 067
    Points
    1 067
    Par défaut
    Citation Envoyé par Frifron Voir le message
    Dans son cas rien, vu qu'il sors de la boucle directement. J'essayer juste de donner un cas plus général :

    Récupérer un itérateur valide apres un erase :
    Si il veut continuer sa boucle apres un erase.

    ne pas invalider un pointeur dans un conteneur :
    Si il y a du traitement entre les 2 instructions suceptibles de lancer une exception, il se retrouve avec un pointeur invalidé dans son conteneur
    On est donc d'accords
    Citation Envoyé par Frifron Voir le message
    Attention toutefois a :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    m_childs.erase(i);
    std::cout<<"Après :"<<(*i)<<std::endl;
    comportement indeterminé si c'est le dernier élément qui est effacé.
    C'est surtout que l'itérateur est totalement invalide après une modification (ajout/suppression) du conteneur qu'il parcourt!
    Ce n'est pas pour rien qu'erase() renvoie un nouvel itérateur valide sur la nouvelle architecture du conteneur après la modification .
    Si c'est le dernier élément qui est supprimé, erase() renvoie la même chose que end().

  10. #10
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut
    Citation Envoyé par Frifron Voir le message
    Attention toutefois a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    m_childs.erase(i);
    std::cout<<"Après :"<<(*i)<<std::endl;
    comportement indeterminé si c'est le dernier élément qui est effacé.
    On est d'accord, c'était pour bien vérifier qu'il faisait quelque chose ou pas, enfin pour avoir un "Après" suite au "Avant"

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

Discussions similaires

  1. [STL]Suppression d'un objet dans un vector
    Par cssiste dans le forum SL & STL
    Réponses: 10
    Dernier message: 19/07/2007, 14h23
  2. [débutant] tester un pointeur sur un objet
    Par hogan dans le forum C++
    Réponses: 26
    Dernier message: 30/03/2007, 10h02
  3. utilisations de pointeurs sur des objets
    Par niarkyzator dans le forum Delphi
    Réponses: 21
    Dernier message: 13/12/2006, 09h42
  4. [Ada] Récupérer un pointeur sur un objet existant
    Par vincnet500 dans le forum Ada
    Réponses: 1
    Dernier message: 14/11/2004, 14h26
  5. vector de pointeurs sur des objet
    Par jean-bobby dans le forum SL & STL
    Réponses: 26
    Dernier message: 06/08/2004, 14h54

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