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 :

Question sur vector::clear()


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 59
    Points : 57
    Points
    57
    Par défaut Question sur vector::clear()
    Bonjour amis développeurs,
    étant sur un projet et n'ayant pas fais de C++ depuis quelque mois maintenant, je décide de m'y remettre.

    Voila rapidement ma question:

    Dans la doc, à propos de vector::clear(), il est dit[source: http://www.cplusplus.com/reference/stl/vector/clear/]:
    void clear ( );

    Clear content
    All the elements of the vector are dropped: their destructors are called, and then they are removed from the vector container, leaving the container with a size of 0.
    de fils en aiguille j'ai donc tester ce code:
    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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    #include <vector>
    #include <string>
    #include <iostream>
     
    using namespace std;
     
    // class de test
    class Test
    {
    private:
    	string	_name;
    	//pointeur de test
    	string	*_job;
     
    public:
    	Test(string const & name, string * const job): _name(name), _job(job){}
    	// delete le pointeur
    	~Test() {
    		//affiche quelque chose pour signifier l'appel au destructeur
    		cout << "dest: " << _name << endl;
    		delete _job; }
     
    	// methode de test
    	void		print() const { cout << this->_name << " my job is: " << *this->_job << endl; }
    };
     
    int	main(int ac, char **av)
    {
    	//initialisation avec de pointeur
    	vector<Test *>	vec;
    	Test			*t1 = new Test("My name is 1", new string("JOB1"));
    	Test			*t2 = new Test("My name is 2", new string("JOB2"));
    	Test			*t3 = new Test("My name is 3", new string("JOB3"));
     
    	// ca marche (encore heureux...)
    	t1->print();
    	t2->print();
    	t3->print();
     
    	//assignation au vector
    	vec.clear();
    	vec.resize(3);
     
    	vec[0] = t1;
    	vec[1] = t2;
    	vec[2] = t3;
     
    	{
    		vector<Test *>::iterator	b = vec.begin();
    		vector<Test *>::iterator	e = vec.end();
    		//je parcour vite fait le vector (la encore, ca marche)
    		for (; b != e; ++b)
    		{
    			cout << "FROM VECTOR: ";
    			(*b)->print();
    		}
     
    		/*
    			Clear() est sence appeller le destructeur de mes Test*, deletant
    			ainsi le _job.
    		*/
    		vec.clear();
    	}
     
    	//Et donc, si j'en crois la doc, ceci ne devrai pas fonctionner:
    	t1->print();
    	t2->print();
    	t3->print();
     
    	/* Ceci appel bien le destructeur et donc plante si decommenter:
    		t1->~Test();
    		t1->print();
    	//*/
     
    	::system("PAUSE");
     
    	return (0);
    }
    EDIT: le code a était édité L71.

    Évidement le code ci-dessus fonctionne et ne plante pas,
    j'en déduis donc que les destructeurs ne sont pas appelés, est-ce normal?

    Je subodore avoir loupé quelque chose () mais j’attends justement vos lumières sur ce point.

    EDIT: Windows MS Visual C++ 2010

    Merci d'avance.

  2. #2
    Membre éprouvé

    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 533
    Points : 1 086
    Points
    1 086
    Par défaut
    Il y a une différence entre détruire un pointeur et détruire l'objet pointé par ce pointeur. Ce que fait l'appel de vector<Test*>::clear(), c'est détruire des éléments de type Test*, rien d'autre.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 59
    Points : 57
    Points
    57
    Par défaut
    Je l'ai bien compris mais, ma question porte sur le faites que clear() ne semble pas appeler les destructeurs des éléments Test* dans le vector. Le fait que la ligne 20 ne s'affiche pas et déjà un problème selon la doc.

  4. #4
    Membre éprouvé

    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 533
    Points : 1 086
    Points
    1 086
    Par défaut
    Tu fais une confusion entre Test* et Test, entre le pointeur et l'objet pointé.

    La méthode vector<Test*>::clear() va supprimer tous les éléments du vecteur, c'est à dire une liste d'adresses mémoire désignant chacune l'emplacement d'un objet Test alloué dynamiquement. En aucun cas elle ne s'engage à appeler l'opérateur delete sur chacun de ces pointeurs !

  5. #5
    Membre averti Avatar de Dalini71
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2008
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2008
    Messages : 181
    Points : 343
    Points
    343
    Par défaut
    Dans ta situation pour que les destructeurs soient appelés, il faut remplacer par Comme dit plus haut, détruire un objet et un pointeur sur un objet, c'est totalement différent, ton code présente de belles fuites mémoires

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

    Informations professionnelles :
    Activité : aucun

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

    Je crois qu'il faut déjà comprendre ce qu'est un pointeur!!!

    Un pointeur n'est jamais qu'une variable numérique "classique" (unsigned int / long / long long, selon l'architecture, ou) pour être tout à fait générique "suffisamment grand pour représenter l'ensemble des adresses mémoires accessibles par le système") qui contient... l'adresse mémoire à laquelle on trouvera l'objet du type indiqué.

    Le fait de détruire le pointeur ne vas donc rien faire d'autre que... détruire cette variable de type numérique, sans rien faire en ce qui concerne l'objet pointé.

    Si tu rempli un vector< Type * > avec des pointeurs sur des objet de type Type créé en utilisant l'allocation dynamique ( new ) tu prend explicitement la responsabilité de la gestion de la durée de vie des objets pointés.

    Le seul moyen de provoquer leur destruction sera de le faire explicitement (en invoquant delete).

    Si tu invoque la fonction clear() sur un tel vecteur de pointeur, tu ne vas détruire QUE les pointeurs, et non les objets pointés par ceux-ci.

    Les réslutats obtenus à ce moment seront :
    • aucun appel au destructeur des objets pointés
    • une belle fuite mémoire si tu ne garde pas, par ailleurs, un pointeur sur chacun des objets pointés par les pointeurs que tu as placé dans le vecteur.

    nota : il existe, dans boost, une classe ptr_vector qui gère correctement les pointeurs en invoquant delete dessus... Il me semble d'ailleurs que cela a été ajouté dans la nouvelle norme

    Si tu veux que ton test fonctionne, il faut donc, au choix :
    • utiliser un vecteur d'objets et non un vecteur de pointeurs
    • utiliser ce ptr_vector car, lui, il gérera correctement la destruction des objets pointés
    Tu devrais, maintenant, avoir toutes les cartes en mains pour comprendre
    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
    Membre éprouvé

    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 533
    Points : 1 086
    Points
    1 086
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Si tu veux que ton test fonctionne, il faut donc, au choix :
    • utiliser un vecteur d'objets et non un vecteur de pointeurs
    • utiliser ce ptr_vector car, lui, il gérera correctement la destruction des objets pointés
    Tu devrais, maintenant, avoir toutes les cartes en mains pour comprendre

    Ajoutons que dans le premier cas, Test::Test() et Test& Test::operator=(const Test&) doivent être impérativement définis.

    Il y a aussi cette méthode qui a le mérite de ne pas alourdir le code par des std::shared_ptr à rallonge :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include <memory>
    class Test {
    public:
      typedef std::shared_ptr<Test> Ptr;
     
      ...
    };
     
    ...
     
    vector<Test::Ptr> vTests;
    vTests.push_back(new Test(...));

  8. #8
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    La FAQ traite de comment libérer de tels conteneurs.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par cob59 Voir le message
    Ajoutons que dans le premier cas, Test::Test() et Test& Test::operator=(const Test&) doivent être impérativement définis.
    Ils le sont d'office, même si, dans le cas présent, il risquent de ne pas faire exactement ce que l'on croit (à cause du pointeur sur string)
    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
    Janvier 2009
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 59
    Points : 57
    Points
    57
    Par défaut
    Merci de vos réponses, j'ai tout compris

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

Discussions similaires

  1. Question sur std::vector
    Par FabaCoeur dans le forum SL & STL
    Réponses: 11
    Dernier message: 24/06/2007, 18h22
  2. question sur les listes/set/vector
    Par deubelte dans le forum SL & STL
    Réponses: 11
    Dernier message: 04/01/2007, 20h41
  3. question sur les listes/set/vector
    Par deubelte dans le forum SL & STL
    Réponses: 16
    Dernier message: 28/12/2006, 20h17
  4. Question sur les vectors
    Par Pragmateek dans le forum SL & STL
    Réponses: 28
    Dernier message: 13/05/2006, 14h55
  5. [debutant STL] question sur les vectors
    Par killerjeff dans le forum SL & STL
    Réponses: 13
    Dernier message: 19/08/2004, 17h32

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