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

C++ Discussion :

Conteneur : Suppression d'élément


Sujet :

C++

  1. #21
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Ben c'est cela qui me chagrine dans cette méthode, cela dépend fortement du conteneur... alors que iter = m_listOp.erase(iter) est bien mieux... non?
    Oui oui on est bien d'accord, lorsqu'un itérateur est renvoyé il faut l'utiliser. La bidouille que je donne n'est utile que pour std::map.

    Pour le conteneur associative, je ne sais pas puisse que la fonction n'est pas identique entre la STL de visual et la STL de SGI...
    Apparemment c'est Visual C++ qui en fait un peu plus que le standard, std::map::erase ne doit rien renvoyer.

  2. #22
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par Laurent Gomila Voir le message
    Oui oui on est bien d'accord, lorsqu'un itérateur est renvoyé il faut l'utiliser. La bidouille que je donne n'est utile que pour std::map.


    Apparemment c'est Visual C++ qui en fait un peu plus que le standard, std::map::erase ne doit rien renvoyer.
    Juste pour terminer avec un vector, mon exemple est pire, en release (pour ne pas avoir les avertissements de debug sous visual) tout ne sera pas testé...
    Dans mon exemple le 5 et le 7 vont être détruit mais le 6 non (après ça crach mais ces normale )

  3. #23
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Es que le remove_if peut être plus propre?

  4. #24
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 337
    Billets dans le blog
    2
    Par défaut
    [EDIT] Attention, le code suivant ne fonctionne pas![/EDIT]

    Bonjour,

    je n'ai pas tout suivi, mais peut-être que ce bout de code pourra aider à la discussion:

    Il s'agit de créer un vecteur de pointeurs sur des int et d'en supprimer tous les entiers impairs (enfin, tous les pointeurs qui pointent sur des entiers impairs)
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    #include <algorithm>
    #include <vector>
    #include <string>
     
    // foncteur pour générer un conteneur qui contient des int*
    struct MyGenerate
    {
    	MyGenerate():count_(0){}
    	int* operator()(){return new int(count_++);}
    	int count_;
    };
     
    // prédicat qui retroune vrai si number pointe sur un entier impair
    bool IsOdd(int *number){ return (*number)&1;}
     
    int main()
    {	
    	// on déclare un vecteur de 10 pointeurs sur un int
    	std::vector<int*> v(10);
     
    	// on génère le vecteur de façon à ce que *(v[i])=i
    	std::generate(v.begin(), v.end(), MyGenerate() );
    	// à ce stade de l'exécution, notre vecteur vaut {0, 1, 2, 3, 4, ..., 9} (sauf que ce sont des pointeurs, pas directement des int)
     
    	// on supprime tous les pointeurs sur des entiers impairs de v
    	std::vector<int*>::iterator it = std::remove_if( v.begin(), v.end(), IsOdd );
    	// à ce stade de l'exécution, notre vecteur vaut {0,2,4,6,8,5,6,7,8,9} (sauf que ce sont des pointeurs, pas directement des int)
     
    	// on supprime la partie superflue
    	std::vector<int*>(v.begin(), it).swap( v );
    	// maintenant, notre vecteur vaut {0,2,4,6,8} (sauf que ce sont des pointeurs, pas directement des int)
     
    	return 0;
    }
    Hope it helps.

  5. #25
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par r0d Voir le message
    Bonjour,

    je n'ai pas tout suivi, mais peut-être que ce bout de code pourra aider à la discussion:

    Il s'agit de créer un vecteur de pointeurs sur des int et d'en supprimer tous les entiers impairs (enfin, tous les pointeurs qui pointent sur des entiers impairs)
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    #include <algorithm>
    #include <vector>
    #include <string>
     
    // foncteur pour générer un conteneur qui contient des int*
    struct MyGenerate
    {
    	MyGenerate():count_(0){}
    	int* operator()(){return new int(count_++);}
    	int count_;
    };
     
    // prédicat qui retroune vrai si number pointe sur un entier impair
    bool IsOdd(int *number){ return (*number)&1;}
     
    int main()
    {	
    	// on déclare un vecteur de 10 pointeurs sur un int
    	std::vector<int*> v(10);
     
    	// on génère le vecteur de façon à ce que *(v[i])=i
    	std::generate(v.begin(), v.end(), MyGenerate() );
    	// à ce stade de l'exécution, notre vecteur vaut {0, 1, 2, 3, 4, ..., 9} (sauf que ce sont des pointeurs, pas directement des int)
     
    	// on supprime tous les pointeurs sur des entiers impairs de v
    	std::vector<int*>::iterator it = std::remove_if( v.begin(), v.end(), IsOdd );
    	// à ce stade de l'exécution, notre vecteur vaut {0,2,4,6,8,5,6,7,8,9} (sauf que ce sont des pointeurs, pas directement des int)
     
    	// on supprime la partie superflue
    	std::vector<int*>(v.begin(), it).swap( v );
    	// maintenant, notre vecteur vaut {0,2,4,6,8} (sauf que ce sont des pointeurs, pas directement des int)
     
    	return 0;
    }
    Hope it helps.
    Il manque le delete sur les pointeur...

  6. #26
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Es que le remove_if peut être plus propre?
    Il faudra tout de même un parcours pour faire un delete sur les éléments, donc ça n'aidera pas beaucoup.

    Il manque le delete sur les pointeur...
    J'allais le dire

  7. #27
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 337
    Billets dans le blog
    2
    Par défaut
    [EDIT] Attention, le code suivant ne fonctionne pas![/EDIT]

    Hum oui heu...

    Alors voyons plutôt le code suivant:
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <iostream>
     
    // une classe de test
    struct Dum
    {
    	Dum(int num):number_(num){}
    	int number_;
    };
     
    struct MyGenerate
    {
    	MyGenerate():count_(0){}
    	Dum* operator()(){return new Dum(count_++);}
    	int count_;
    };
     
    bool IsOdd(Dum *dum){ return (dum->number_)&1;}
     
    // juste pour afficher le résultat dans la console, pour voir ce qu'il se passe
    void PrintMyVector(std::vector<Dum*> v)
    {
    	struct PrintDum{
    		void operator()(Dum* dum){std::cout << dum->number_ << " ";}
    	};
     
    	std::for_each( v.begin(), v.end(), PrintDum() );
    	std::cout << std::endl;
    }
     
    struct DeleteDum{ void operator()(Dum* dum){delete dum;} };
     
    int main()
    {	
    	std::vector<Dum*> v(10);
    	std::generate(v.begin(), v.end(), MyGenerate() );
    	PrintMyVector(v);
     
    	std::vector<Dum*>::iterator it = std::remove_if( v.begin(), v.end(), IsOdd );
    	PrintMyVector(v);
     
    	std::for_each( it, v.end(), DeleteDum() );
    	PrintMyVector(v);
     
    	std::vector<Dum*>(v.begin(), it).swap( v );
    	PrintMyVector(v);
     
    	return 0;
    }
    Bon, c'est sans doute un peu trop compliqué pour ce qu'on veut faire je crois
    mais ça marche [edit]non, ça ne marche pas[/edit]

    ps: Je fais un peu de pub pour les algorithmes

  8. #28
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par Mongaulois Voir le message
    Es que le remove_if peut être plus propre?
    en fait c'est pas une bonne idée du tout...
    j'ai essayé cela :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    iter_debut_delete = std::remove_if(m_listOp.begin(),m_listOp.end(),&test);
    std::for_each(iter_debut_delete,m_listOp.end(),&delete_pointeur );
    m_listOp.erase(iter_debut_delete,m_listOp.end());

    Comme la partie aprés l'iterateur donné par le remove_if est indéfinie, je me suis retrouver avec le même pointeur à deux endroit du conteneur d'où :
    - j'ai perdu des éléments à détruire(fuite mémoire)
    - j'ai détruit des pointeur utiliser dans la partie "valide" du conteneur (situé entre le début et l'itérateur retourné)....

  9. #29
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 337
    Billets dans le blog
    2
    Par défaut
    En effet!!!

    Bon nan mais tfaçon, il faut pas utiliser des pointeurs dans les conteneurs!!!

  10. #30
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Comme la partie aprés l'iterateur donné par le remove_if est indéfinie
    Non non, c'est juste ton iter_fin_delete qui est indéfini (a priori). Les éléments à supprimer se trouvent simplement entre l'itérateur renvoyé par remove_if et la fin du conteneur.

  11. #31
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par Laurent Gomila Voir le message
    Non non, c'est juste ton iter_fin_delete qui est indéfini (a priori). Les éléments à supprimer se trouvent simplement entre l'itérateur renvoyé par remove_if et la fin du conteneur.
    Desolé,
    c'était un morceau du code, j'ai corrigé en conséquence.

    Mais cela ne change pas le problème...
    En faite remove_if (sous visual 2005) parcour le conteneur et remplie par un = (non un swap) en partant du début du conteneur tous les objets qui valident le test. Du coup,
    - entre le debut et l'iterateur retourné, on as remplacé des pointeurs qui ne vérifient pas test par des pointeur squi le vérifient (fuite memoire),

    - dans la second partie on va retrouver des pointeurs qui vérifient le test et que l'on va détruire...

  12. #32
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Où une fuite mémoire ? Les éléments sont les mêmes, simplement dans un ordre différent.

    Si tu veux parler des erreurs inhérentes au fait que la classe utilisée en exemple gère mal son pointeur, et bien... c'est la faute de la classe

  13. #33
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 337
    Billets dans le blog
    2
    Par défaut
    Mééééé!!!

    Que devrais-je faire? Redéfinir l'opérateur -> ?

  14. #34
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par Laurent Gomila Voir le message
    Où une fuite mémoire ? Les éléments sont les mêmes, simplement dans un ordre différent.
    Pas sous visual 2005. C'est bien le problème.
    pour la suite
    1 5 10 22 6 7 1 2 3
    un remove_if qui doit vérifier si l'element est inférieur à 5 on aura :
    1 1 2 3 6 7 1 2 3

    Ben pour les pointeur, cela va faire disparaître des pointeurs, et donc une fuite mémoire... et aussi faire des copie de pointeur que l'on voulais détruire...

  15. #35
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 337
    Billets dans le blog
    2
    Par défaut
    Sinon, mon exemple fonctionne si on remplace remove_if() par partition(). Au moins, on ne supprime rien, et on ne s'embrouille pas les pointeurs.

  16. #36
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Ah oui c'est vrai, remove assure seulement que les éléments de begin() à l'itérateur renvoyé ont passé la condition. On ne peut donc pas utiliser les éléments de it à end(), par exemple pour les détruire à coup de delete.

  17. #37
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Laurent Gomila Voir le message
    Pour une liste oui, mais pour une map erase ne renvoie rien (faudra qu'on m'explique pourquoi d'ailleurs).
    Pas de bonnes raisons. Ce sera fixé en C++200X.

  18. #38
    Membre averti
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 23
    Par défaut
    Ok,

    Ce code que j'ai trouvé dans la discussion me semble
    super pour mon cas :

    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
     
     
    std::list<Triangle*> liste_tri;
    std::list<Triangle*>::iterator iter;
    for (iter = liste_tri.begin(); iter != liste_tri.end(); )
    {
        if (*iter == .....) // Condition
        {
             delete *iter; // On détruit l'élément pointé
            iter= liste_tri.erase(iter);  
        }
        else
        {
              ++iter;
        }
    }
    Juste une dernière question c'est quoi la différence entre erase et remove ?

    Merci à tous pour votre aide.
    MProg

  19. #39
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Juste une dernière question c'est quoi la différence entre erase et remove ?
    Ca dépend du contexte. Certaines fois remove ne va pas supprimer physiquement les éléments (std::remove) parfois il va le faire (std::list::remove).
    Bref je te conseille de regarder la doc à chaque fois que tu utilises l'une de ces fonctions.

  20. #40
    Membre averti
    Inscrit en
    Mai 2007
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 26
    Par défaut
    dans le cas d'une list, erase permet de suprimer l'element à partir de son iterator ou les éléments entre deux iterator de début et de fin. remove permet de suprimer un élément par sa valeur.

    erase(iterator position)
    erase(iterator début, iterator fin)

    remove( const T& valeur )

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. [Tableaux] suppression d'élément d'un tableau
    Par maysa dans le forum Langage
    Réponses: 8
    Dernier message: 04/04/2007, 09h37
  2. Suppression d'éléments dans un tableau (Array)
    Par jeremie74 dans le forum Flash
    Réponses: 4
    Dernier message: 06/03/2007, 14h54
  3. Suppression d' éléments dans une liste.
    Par conan76 dans le forum ASP.NET
    Réponses: 3
    Dernier message: 02/03/2007, 10h33
  4. [Tableaux] Suppression d'élément de tableau
    Par jpascal dans le forum Langage
    Réponses: 2
    Dernier message: 27/12/2006, 16h11
  5. [xslt] Suppression des éléments sans contenu.
    Par dibbouk dans le forum XSL/XSLT/XPATH
    Réponses: 6
    Dernier message: 17/06/2005, 18h17

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