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 :

delete et std::vector


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 114
    Points : 57
    Points
    57
    Par défaut delete et std::vector
    Bonjour tout le monde,

    j'vais un probelme d'allocation et de desallocation de tableau et qqun m'a cosneillé de faire ça avec des std::vector.

    alros je me demandais si ca posait u probleme de melanger des delete et des std::vector ?

    Parce que j'ai deja fait un bon bout de mon programme et j'utilise bcp de new et delete pour certaine variable et puis pour mon tableau je pense que je vais utiliser std::vector car ca a l'air simple d'utilisation. Est ce que ca pose un porbleme ?

    Merci pour vos réponse,

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Tout dépend de ce que tu mets dans ton tableau...:
    • A la base, std::vector, c'est un conteneur tout à fait générique.
    • Généralement, quand tu utilise le mot clé new, cela signifie
      1. que tu veux prendre le contrôle de la durée de vie d'un objet
      2. que tu accepte d'en prendre la responsabilité

    De manière générale, il faut savoir que toute utilisation de new doit trouver son pendant dans une utilisation de delete, et que le fait d'utiliser un std::vector n'y changera rien... Même si c'est de nature à en faciliter l'usage

    J'ai écrit que cela dépend de ce que tu met dans ton tableau... cela mérite une petite précision:

    Si, dans ton tableau, tu déclare ton tableau ne contenant que des objet (sous une forme proche de std::vector<TonType> tab), tu n'a *sans doute* aucun besoin de faire des appels à new, et donc, tu n'a pas d'avantage besoin de faire appel à delete (mais il faut être attentif au fait que tes objets n'auront une durée de vie qu'en tout cas égale à celle du tableau).

    Si, par contre, tu déclare ton tableau comme contenant des pointeurs sur tes objets (sous une forme proche de std::vector<TonType*> tab) - et les raisons "qui font que" sont variées et multiples - il est fort vraissemblable que chaque objet ajouté au tableau soit créé avec le recours à new, et donc que la mémoire allouée à tout objet que tu supprimera de ton tableau devra être libérée par le delete correspondant, y compris (et surtout ) si tu veux carrément vider le tableau d'objets.

    Maintenant, on peut *envisager* le fait que tu veuille carrément disposer d'un "gestionnaire d'objets"... Et, dans ce cas, la programmation orientée objet peut venir à ton secours, de par les méthodes que tu peux donner à au type "gestionnaire d'objets", et, principalement son destructeur, voire, une méthode perso "SuppressAllElement"
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 114
    Points : 57
    Points
    57
    Par défaut
    ok merci de tes explications.

    Comme tu le dis dans celles ci j'utilise un std::vector<TComposant*> Composants. (TComposant est une classe que j'ai créé, et Composants c'est mon tableau qui va contenir tous mes TComposant). Je vais donc utilisé des new pour chaque nouvelle case du tableau. Il faudra donc que j'aille supprimer avec delete chaque objet par la suite.

    Mais alors je ne comprends plus l'interet d'utilsier std::vector par rapport a un tableau classique qui contient lui aussi des pointeurs ?

    merci de m'eclaircir !

  4. #4
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Effectivement, si ton conteneur contient des pointeurs, il te faudra également désallouer à la main via des "delete".
    L'avantage de std::vector reste la réallocation de mémoire (push_back() ).

    Maintenant, il existe un conteneur exactement comme std::vector mais exprès pour les pointeurs, c'est boost::ptr_vector !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector <MaClasse*> vect;
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::ptr_vector<MaClasse> vect2; // ou std::tr1::ptr_vector
    sont complètement équivalent, et boost supprimera automatiquement les espaces mémoires...

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 114
    Points : 57
    Points
    57
    Par défaut
    ok, donc dans mon cas je ferais mieux d'utilier boost.

    Enfaite derriere mes questions se cache un probleme.

    j'alloue mon tableau à un moment de mon programme puis je le desalloue lorsque une autre classe s'en est servie.

    Le probleme c'est qu'au moment de le desallouer en fonction de ce qui sais passé je ne suis pas sur qu'il est été alloué!
    Du coup lorsque je désalloue les pointeurs contenu dans mon tableau, si ceci n'ont pas été allouer alors mon programme plante.

    Donc si j'utilise std::vector ou boost:: je pourrais tester si mes pointeurs ont été allouer ou même directement desallouer le vector sans avoir à savoir si mes pointeurs contenu dans celui ci ont été allouer, n'est ce pas ?

    Est ce que je suis clair ? sinon demander moi des precisions car j'aimerais etre sur de ce que je vais faire !


    Merci encore !

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    En fait, tu semble confirmer ce que je subodorais: ce qu'il te faut, c'est un moyen cohérent de gérer la durée de vie de tes TComposant...

    Dés lors, ce que je te conseillerais peut etre, c'est d'envisager la création d'une classe que l'on pourrait nommer "ComposantHolder", par exemple, et qui pourrait prendre comme base un code du genre de
    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
    class CompsantHolder
    {
        public:
            ComposantHolder(); /* constructeur par défaut */
            ComposantHolder(size_t nbelem);/* constructeur si on sait le nombre
                                            * d'élément à insérer à la base */
            ~ComposantHolder(); /* destructeur du gestionnaire */
            void AddComposant(size_t nb); /* permet d'ajouter des composants */
            void RemoveComposant(size_t index);/* permet d'en supprimer un */
            void RemoveComposants(size_t inddeb, size_t indfin);/* permet d'en 
                                                                 * supprimer plusieurs */
            void ClearAll() /* les supprimes tous */
            TComposant* operator[](size_t ind);/* permet de récupérer le 
                                                * composant à l'index donné (RW)*/
            const TComposant* operator[](size_t ind) const;/* permet de récupérer 
                                                          * le composant à l'index donné 
                                                          * (RO)*/
            /* pour faire "bonne mesure" */
            size_t Size() const; /* indique le nombre de composants existant */
        private:
            std::vector<TComposant*> tab;
    };
    [EDIT]l'implémentation en serait, afin de s'assurer que l'on n'oublie pas de libérer la mémoire, dans le genre de
    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
    ComposantHolder::ComposantHolder()
    {
        /*simplement rien :D */
    }
    ComposantHolder::ComposantHolder(size_t nbcomposant)
    {
        for(size_t i=0;i<nbcomposant;i++)
            tab.push_back(new TComposant);
    }
    ComposantHolder::~ComposantHolder()
    {
        for(size_t i=0;i<tab.size();i++)
            delete tab[i];
        tab.clear();
    }
    void ComposantHolder::AddComposant(size_t nb)
    {
        for(size_t i=0;i<nb;i++)
            tab.push_back(new TComposant);
    }
    void ComposantHolder::RemoveComposant(size_t index)
    {
        if(tab.size()>index)
        {
            /* libération de la mémoire du composant vise */
            delete tab[index];
            /* et suppression de l'élément */
            tab.remove(tab.begin()+index);
        }
    }
    /* pour les autres... ce devrait etre facile :D */
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    J'ai exactement compris ton problème, et koala01 y a très bien répondu. C'est une technique très répandue et il serait bon que tu assimiles ce qui est dit dans le message précédent, car cela te servira beaucoup.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 114
    Points : 57
    Points
    57
    Par défaut
    Citation Envoyé par Alp Voir le message
    J'ai exactement compris ton problème, et koala01 y a très bien répondu. C'est une technique très répandue et il serait bon que tu assimiles ce qui est dit dans le message précédent, car cela te servira beaucoup.
    j'ai bien saisi le code donner par koala01, mais dans mon cas je n'ai pas besoin d'autant de fonction ,mais juste besoin de faire :

    - soit mon vecteur est rempli et je supprime les pointeur a l'interieur et le vecteur
    - soit mon vecteur est vide et je supprime seulement le vecteur.


    Mais en tout cas merci, ca m'aide bcp pour l'utilisation des vecteurs que je pensais plus compliqué que ca dans leur utiliation.


    à vous !

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Mais, pourquoi supprimer le vecteur

    En plus, un vecteur n'est jamais "rempli", vu que l'espace qui lui est alloué augmente en fonction des besoins...

    Tu peux, effectivement, sans doute te contenter d'une fonction Add, de l'operateur [] et de la fonction "Clear()" (qui libère la mémoire de tous les TComposants et qui vide le vecteur), si ton analyse te porte à en être sûr.

    Mais l'idée générale est:

    1. Que le ComposantHolder soit le seul responsable de l'allocation de mémoire ou de la libération de la mémoire allouée à un TComposant
    2. Que le ComposantHolder maintienne la liste de tous les Composant qu'on lui a demandé de créer.
    3. Qu'il faille passer systématiquement par un ComposantHolder pour obtenir un nouveau TComposant, ou détruire celui qui est devenu inutile.
      *Idealement*, il faudrait d'ailleurs interdire l'acces aux constructeurs et au destructeur du TComposant en les déclarant privés (ou protégés, s'il y a de l'héritage) et en déclarant ComposantHolder ami de TComposant.
    4. Que la destruction - entre autre du fait d'une sortie de portée - d'un ComposantHolder provoque systématiquement la libération de la mémoire alloué à l'ensemble des TComposant qui n'auront pas été détruits
    5. Qu'un ComposantHolder ne puisse pas être copié, pour éviter les problème de double libération de la mémoire allouée au TComposant
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 114
    Points : 57
    Points
    57
    Par défaut
    J'ai utilisé le erme supprimer parce qu eje comprends encore mal le concept de vecteur mais j'ai compris qu'il ne servait a rien de la supprimer vu qu'il est vide quand on le clear.


    merci de ton aide koala01

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

Discussions similaires

  1. Plantage sur deletion de std::vector
    Par uriotcea dans le forum C++
    Réponses: 8
    Dernier message: 20/02/2012, 21h09
  2. delete []double et std::vector::resize()
    Par nsarras dans le forum C++
    Réponses: 4
    Dernier message: 03/05/2011, 10h03
  3. char[50] et std::vector<>
    Par tut dans le forum SL & STL
    Réponses: 9
    Dernier message: 12/10/2004, 13h26
  4. Réponses: 8
    Dernier message: 26/08/2004, 18h59
  5. Sauvegarde std::vector dans un .ini
    Par mick74 dans le forum MFC
    Réponses: 2
    Dernier message: 12/05/2004, 13h30

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