2010-01-31 7 views
0

Mon C++ est un peu rouillé mais j'ai fait un programme qui inverse une liste chaînée et maintenant j'essaye d'écrire les destructeurs appropriés mais je ne sais pas exactement quoi détruire. Voici les définitions de mes classes:Exemple de destructeur C++

class LinkedList 
{ 
    private:ListElement *start; 
    public:LinkedList(); 
    public:void AddElement(int val); 
    public:void PrintList(); 
    public:void InvertList(); 
}; 

class ListElement 
{ 
    public:int value; 
    public:ListElement * link; 
    public:ListElement(int val); 
    public:ListElement(); 
}; 


class Stack 
{ 

private:ListElement ** stack; 
private:int index; 
public:Stack(int size); 
public:void push(ListElement * le); 
public:ListElement * pop(); 

}; 

La pile est pour lorsque j'inverse la liste. En tout cas ... Comment pourrais-je écrire les destructeurs pour ceux-ci? Je pensais:

Pour le ListElement faites la valeur 0 et le lien 0 (NULL).

Pour le LinkedList parcourir les éléments et appeler le ListElementDestructor pour tous.

Je ne suis pas très sûr à ce sujet parce que si je comprends bien le destructeur appelle automatiquement les destructeurs des objets membres, donc écrire uniquement un destructeur vide pour LinkedList suffit dans ce cas? Je ne sais pas ... c'est pourquoi je demande

Pour la pile je ne sais pas ... les pointeurs sont déjà 0 (NULL) après que la liste soit inversée car ils sont tous popés.

Je suis un peu confus. Quelqu'un peut-il aider? Merci d'avance.

+4

Ne serait-il pas plus facile d'inverser la direction des pointeurs entre les éléments plutôt que d'utiliser une pile? – Yacoby

+4

La répétition des mots-clés privés et publics est inutile. Just private: // Déclarations de variables privées public: // Public var déclarations – batbrat

+1

Je suggère également de rendre le membre "link" privé de listElement, et de lui fournir un accès en lecture seule par un next () méthode – davka

Répondre

1

Pour la ListElement rendre la valeur 0 et le lien 0 (NULL).

Vous n'avez pas besoin de réinitialiser l'une des valeurs du destructeur, car les valeurs n'existeront pas après l'exécution du destructeur.

La principale chose que vous devez être sûr que tous les éléments alloués sur le tas (i.e. aide new) sont supprimés à l'aide delete (ou delete [] dans le cas des tableaux).

Pour la liste LinkedList, parcourez les éléments et appelez ListElementDestructor pour chacun d'entre eux.

Pour un objet alloué sur la pile, il est automatiquement appelé lorsque l'objet sort de la portée.
Pour un objet alloué dynamiquement (c'est-à-dire créé en utilisant new), le destructeur est appelé lorsque est supprimé en utilisant delete.En d'autres termes, vous n'avez pas besoin d'appeler des destructeurs comme ils sont appelés automatiquement si vous nettoyez vos objets correctement. Etant donné (je suppose) que vous allouez de nouveaux ListElements sur le tas dans la classe LinkedList, vous devez vous assurer que dans le destructeur LinkedList, chaque ListElement est supprimé dans le destructeur en parcourant la liste et en appelant delete sur chaque ListElement (après avoir récupéré l'adresse de l'élément suivant de la liste bien sûr). Quelque chose comme ceci:

ListElement* current = list.start;  
while(current){ 
    ListElement* next = current->next; 
    delete current; 
    current = next; 
} 

Il n'y a rien dans la classe ListElement qui a besoin de nettoyage, comme bien qu'il ait un pointeur sur l'élément suivant la suppression devrait probablement être traitée dans la classe LinkedList, ce qui signifie qu'il ne besoin d'un destructeur.
Il n'est pas nécessaire d'écrire un destructeur pour chaque classe, car le compilateur en générera automatiquement un pour vous.

Comme je l'ai dit dans les commentaires, vous ne devriez pas utiliser une pile pour inverser une liste chaînée. Vous devriez juste échanger la direction des pointeurs.
Un exemple rapide d'à peu près le genre de chose que vous voulez.

ListElement* previous = 0; 
ListElement* current = list.start; 

while(current->next){ 
    //copy the address of current item on the list 
    ListElement* next = current->next; 

    //point the current list item to the previous list item 
    current->next = previous; 

    //set the current list item to the next list item 
    current = next; 

    //and the previous list item to the current one 
    previous = current; 
} 
//set the start of the list to what was the end 
list.start = current; 
+0

C'est ainsi que j'ai appris à le faire au lycée avec une pile. Si vous pouviez me montrer comment inverser les pointeurs, je serais très obligé. Je n'avais aucune idée que cela pourrait être fait d'une autre manière. C'est juste la première chose qui m'a traversé la tête. Je suis ouvert à toute autre solution. J'apprécierais en fait. – Para

+0

@Para J'ai modifié dans mon message un code approximatif (et non testé) pour inverser une liste chaînée en inversant les pointeurs. Même si cela ne fonctionne pas correctement à 100%, cela devrait vous donner une idée de la façon de procéder. – Yacoby

9

Vous détruisez des choses qui doivent être détruites. Si votre classe a créé des objets en utilisant new, vous avez probablement besoin d'un destructeur qui les supprime en utilisant un destructeur. Notez que les conteneurs tels que LinkedList ne doivent contenir que des éléments qui ont été alloués dynamiquement ou ceux qui ne le sont pas. Si vous mélangez les deux ou si vous mélangez des originaux et des copies, comme vous le supposez, vous devez probablement utiliser des pointeurs intelligents ou le comptage des références. Deuxièmement, si vous avez vraiment besoin d'inverser une liste à lien unique (quelque chose que vous n'avez jamais eu besoin de faire en 30 ans de programmation), vous utilisez simplement la mauvaise structure de données - vous devriez utiliser une liste doublement chaînée , auquel cas il n'y a pas besoin de faire quoi que ce soit.

Et troisièmement, puis-je dire que votre style C++ est non-idiomatique et pour moi presque illisible - faire ressembler C++ à Java n'est pas une bonne idée. Changer à:

class LinkedList 
{ 
    private: 
     ListElement *start; 
    public: 
     LinkedList(); 
     void AddElement(int val); 
     void PrintList(); 
     void InvertList(); 
}; 
+0

Eh bien ... Je l'ai eu comme une question pour un entretien d'embauche une fois: "Ecrire le code approprié (y compris la structure de classe) pour inverser une seule liste liée". Je souligne "liste à un seul lien". Je l'ai aussi fait au lycée de Pascal et au lycée de Java. Désolé de faire ressembler C++ à Java Je ne voulais vraiment pas dire que je me suis habitué à écrire des choses de cette façon. – Para

1

La classe LinkedList crée ListElements. Donc, vous devez boucle du début à la fin de la liste (sauf si elle est vide.) Et:

delete currentElement; 

Dans le destructor LinkedList. Puisque la ListElement stocke la valeur comme un 'int', vous n'avez pas vraiment besoin de libérer de la mémoire ici. Juste comme tu pensais.

Encore une fois, pas besoin de libérer de la mémoire dans le destructeur de la classe Stack. En général, supprimez tout ce que vous avez nouveau! Et laissez une personne (classe) être responsable du travail!