Appel récursif au destructeur : une horreur ?
Bonjour à tous,
Dans un but purement d'entrainement, je code une classe pour gérer une liste chainée.
Pour cela j'ai choisi la technique du premier élément bidon (le premier élément n'en est pas un, c'est juste une accroche, créé lors de l'appel du constructeur).
Tout fonctionne pour le moment bien, mais j'aimerais votre avis sur mon destructeur...
Comme chaque élément ajouté dans la liste est créé dynamiquement avec un "new", j'avais besoin de gérer la libération de la mémoire dans le destructeur.
Une technique que j'ai trouvé est tout simplement de sauter le premier élément (bidon), puis dans le cas général :
sauvegarder l'élément suivant
appelé le destructeur dessus si il n'est pas nul
ça permet de parcourir et de détruire tous les éléments de la liste...
En exécution ça plante pas, en console j'ai une trace de la suppression de tous les éléments, bref ça à l'air de marcher.
Mais j'aimerai votre avis de pro.
Est-ce inutile, dangereux, idiot ?
Voici le code :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
Noeud::~Noeud()
{
Noeud *maillon_suivant = NULL;
//premier appel du destructeur, depuis la tete de la liste, la valeur de this. On a pas besoin de faire un delete de cet élément, il n'a pas été alloué dynamiquement
if ( this->est_accroche_liste() ){
maillon_suivant = this->maillon_suivant;
maillon_suivant->~Noeud();
}
//un appel après, sur un maillon quelquonque qui doit être supprimé
else{
cout << "Suppression de l'element "+ this->valeur << endl;
maillon_suivant = this->maillon_suivant;//on sauve le suivant
//Si le maillon suivant n'est pas à NULL (on n'est pas au bout de la chaine), on appel le destructeur sur le maillon suivant
if( maillon_suivant != NULL){
//cout << "Maillon suivant : "+ maillon_suivant->valeur << endl;
delete maillon_suivant;
}
}
} |
et le code complet de l'implémentation de la classe :
Code:
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
#include "../include/Noeud.h"
Noeud::Noeud(): valeur("NULL"), maillon_suivant(NULL)
{
//cout << "Construction du premier element" << endl;
}
Noeud::Noeud(string s): valeur(s), maillon_suivant(NULL)
{
//cout << "Construction de l\' element :"+s << endl;
}
Noeud::~Noeud()
{
Noeud *maillon_suivant = NULL;
//premier appel du destructeur, depuis la tete de la liste, la valeur de this. On a pas besoin de faire un delete de cet élément, il n'a pas été alloué dynamiquement
if ( this->est_accroche_liste() ){
maillon_suivant = this->maillon_suivant;
maillon_suivant->~Noeud();
}
//un appel après, sur un maillon quelquonque qui doit être supprimé
else{
cout << "Suppression de l'element "+ this->valeur << endl;
maillon_suivant = this->maillon_suivant;//on sauve le suivant
//Si le maillon suivant n'est pas à NULL (on n'est pas au bout de la chaine), on appel le destructeur sur le maillon suivant
if( maillon_suivant != NULL){
//cout << "Maillon suivant : "+ maillon_suivant->valeur << endl;
delete maillon_suivant;
}
}
}
bool Noeud::est_accroche_liste(){
return valeur == "NULL";
}
bool Noeud::est_dernier_maillon(){
return maillon_suivant == NULL;
}
void Noeud::ajout_au_bout(string valeur_a_ajouter){
Noeud *noeud_a_ajouter = new Noeud(valeur_a_ajouter);
Noeud* noeud_actuel = this;
while( noeud_actuel->maillon_suivant != NULL){
noeud_actuel = noeud_actuel->maillon_suivant;
}
noeud_actuel->maillon_suivant = noeud_a_ajouter;
}
void Noeud::ajout(string valeur_a_ajouter, int indice){
int indice_depart = 1;
Noeud *noeud_a_ajouter = new Noeud(valeur_a_ajouter);
Noeud *noeud_actuel = this;
Noeud *ancien_noeud_suivant = NULL;
while( noeud_actuel->maillon_suivant != NULL && indice_depart < indice){
noeud_actuel = noeud_actuel->maillon_suivant;
indice_depart++;
}
//une fois le bon élément atteint, on insère le nouveau après cet élément, puis on le raccroche à la suite de la liste
ancien_noeud_suivant = noeud_actuel->maillon_suivant;
noeud_actuel->maillon_suivant = noeud_a_ajouter;
noeud_a_ajouter->maillon_suivant = ancien_noeud_suivant;
}
string Noeud::get_valeur_noeud(int indice){
int indice_actuel = 0;
Noeud* noeud_actuel = this;
while( noeud_actuel->maillon_suivant != NULL && indice_actuel < indice){
noeud_actuel = noeud_actuel->maillon_suivant;
indice_actuel++;
}
return noeud_actuel->valeur;
}
int Noeud::get_taille(){
int taille = 0;
Noeud* noeud_actuel = this;
while( noeud_actuel->maillon_suivant != NULL){
noeud_actuel = noeud_actuel->maillon_suivant;
taille++;
}
return taille;
}
void Noeud::parcours(){
Noeud* Noeud_actuel = this;
if( est_accroche_liste()){
Noeud_actuel = this->maillon_suivant;
}
while( Noeud_actuel->maillon_suivant != NULL ){
cout << "Dans while " + Noeud_actuel->valeur << endl;
Noeud_actuel = Noeud_actuel->maillon_suivant;
}
cout << "Dernière valeur : " + Noeud_actuel->valeur << endl;//On n'oublie pas d'afficher la dernière valeur
} |
D'avance merci ;)
PS : je sais bien sûr, y'a la STD et tout ça, c'est juste pour m'entrainer et bien comprendre :)