Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2501 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Incomprehension appels destructeurs et vector…

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Incomprehension appels destructeurs et vector…

n°1585112
chalumeau
Posté le 11-07-2007 à 12:03:15  profilanswer
 

Bonjour, j'ai beaucoup de mal à comprendre l'ordre d'appel des destructeurs pour des objets insérés dans des vecteurs.
Le comportement est limpide quand je stocke des pointeur sur mes objets (je suis responsable explicitement des libérations), mais si je stocke des objets eux même...
 
Je pensais que lorsque j'instanciais un objet, via  

Code :
  1. Truc truc();

, la durée de vie de l'instance était gérée automatiquement (appel au destructeur lorsque je sors du scope de définition).
 
Maintenant, j'ai envie de mettre un de mes objets dans un vecteur...Il me semblait que l'appel au destructeur devenait de la résponsabilité du vecteur...Si je retire l'objet, ou si je vide le vecteurs j'imaginais que les destructeurs seraient appellés.
 
Dans un élan de lucidité, je me décide à tester l'air de rien ce comportement, avant de ravager du vrai code...
Et là c'est le drame.
 
De mon main, j'appelle une méthode qui instancie 5 objets Truc, et qui les place dans un vecteur.  
Les trucs ne sont définis que dans le scope d'une boucle, le vecteur pour toute la fonction.
Je compte bien 5 appels aux constructeurs.
Je compte heu...des tonnes d'appels aux destructeurs...
 
Alors je vois bien que je m'y prends mal, et que je ferrais mieux de stocker des pointeurs...mais quand même...une ame génereuse pourrait-elle m'expliquer le comportement que j'observe ?  :whistle:  
 

Code :
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. class Truc
  5. {
  6. int mi;
  7. public:
  8.     Truc(int i)
  9.     {
  10.      mi = i;
  11.      cout << "Constructeur " << mi << endl;
  12.  }
  13.     ~Truc(void)
  14.     {
  15.      cout << "Destructeur "  << mi << endl;
  16.  }
  17. };
  18. void tableau(void)
  19. {
  20. cout << endl << "Début Tableau" << endl << endl;
  21. vector<Truc> vect;
  22. for (int i=0; i<5; i++)
  23. {
  24.  cout << i << endl;
  25.  Truc truc(i);
  26.  vect.push_back(truc);
  27. }
  28. cout << endl << "Fin Tableau" << endl;
  29. }
  30. int main(void)
  31. {
  32. tableau();
  33.   cout << endl << "Fini" << endl;
  34.   return 0;
  35. }


 
Ce que ca fait lorsque c'est executé (Linux, Windows même combat):


Début Tableau
 
0
Constructeur 0
Destructeur 0
1
Constructeur 1
Destructeur 0
Destructeur 1
2
Constructeur 2
Destructeur 0
Destructeur 1
Destructeur 2
3
Constructeur 3
Destructeur 3
4
Constructeur 4
Destructeur 0
Destructeur 1
Destructeur 2
Destructeur 3
Destructeur 4
 
Fin Tableau
Destructeur 0
Destructeur 1
Destructeur 2
Destructeur 3
Destructeur 4
 
Fini

mood
Publicité
Posté le 11-07-2007 à 12:03:15  profilanswer
 

n°1585128
IrmatDen
Posté le 11-07-2007 à 12:46:04  profilanswer
 

Salut,

 

Quand tu places un objet dans un vector, il y a le constructeur par copie qui est appellé, du coup, il est instancié au moins 2 fois. Ensuite le vector va réallouer son tableau pour faire de la place, d'où l'appel de plusieurs destructeurs.
Edit: ces réallocations générant d'autres instances créées par copie, mais comme tu ne traces pas cette instanciation, tu ne le sais pas; ajoute un constructeur par copie et tu verras mieux ce qu'il se passe ;)


Message édité par IrmatDen le 11-07-2007 à 12:47:25
n°1585131
LePhasme
Les Belges domineront le monde
Posté le 11-07-2007 à 12:48:40  profilanswer
 

Le C++ est un peu loin pour moi mais je pense que ça a à voir avec le constructeur par recopie et le fait que tu stocke tes objets par valeur.

 

J'espère ne pas avoir dit de conneries.

 

Edit : [:benou_grilled]


Message édité par LePhasme le 11-07-2007 à 12:49:18
n°1585193
chalumeau
Posté le 11-07-2007 à 14:30:57  profilanswer
 

Merci beaucoup, c 'est nettement plus clair !
 
Après avoir rajouté des traces dans le constructeur par copie, tout est devenu plus limpide.
Un appel à celui-ci est effectué avant chaque push_back.  
 
Vous avez doublement raison, lors des resize du vecteur on se retrouve à recopier les membres du vecteur, et à construire de nouvelles copies !
 
En disant au vecteur du départ que sa taille va être de 5 (et donc en évitant le mécanisme de resize et donc de recopie) on tombe sur un comportement beaucoup plus compréhensible, avec appels aux destructeurs des objets "initiaux", puis copie de ceux-ci lorsqu'ils sont ajoutés, et enfin destruction de tout le monde lorsque le vecteur sort du scope.  :bounce:  
 
 
C'est un peu déstabilisant de voir qu'il copie à chaque insertion, naïvement j'imaginais un compteur du nombre de réferences, ou un truc dans ce goût là...Déstabilisant aussi que le resize oblige à réinstancier tout le monde  :(  
 
Mais en tout cas le comportement est plus clair ! Merci beaucoup  :)  
 
J'imagine que la morale que je dois en tirer c'est qu'il vaut mieux gérer soit même les désallocations, en ne stockant que des pointeurs...histoire d'éviter des tonnes d'instanciation et de destruction...

n°1585194
IrmatDen
Posté le 11-07-2007 à 14:33:10  profilanswer
 

De préférence des boost::shared_ptr, tu auras le comportement que tu as attend au niveau d'un compteur de référence ;)

n°1585397
boulgakov
Posté le 11-07-2007 à 18:29:54  profilanswer
 

chalumeau a écrit :

[...] Dans un élan de lucidité, je me décide à tester l'air de rien ce comportement, avant de ravager du vrai code... [...]


 
 :love:  
 
Ca change des "bonjour je compran pas pourquoi ma methode WfGet3DObject faire un segmentation core sous Borland 5.2 kan je veux fer mon projet avec la librairie trucmuche, sympa de m'aidé svp ça uuurge !"
 
(Désolé pour l'inutilité totale de ce message)
 

n°1585400
Taz
bisounours-codeur
Posté le 11-07-2007 à 18:36:46  profilanswer
 

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Incomprehension appels destructeurs et vector…

 

Sujets relatifs
Gestion appels utilisateurs[VBA-Excel] Construction d'un arbre d'appels
Appels systèmes, infos, explications...Réinitialisation vector [RESOLU]
pointeur sur std::vector<T>Probleme avec la classe Vector ?!
[java] ajouter/afficher des Vector dans une JTable[C++]un vector de references?!
Ipbx Appels entrants[VBA] appels fonctions .dll C/C++
Plus de sujets relatifs à : Incomprehension appels destructeurs et vector…


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)