2010-02-15 17 views
12

È un distruttore LinkedList valido? Sono ancora un po 'confuso da loro.Scrittura di un distruttore LinkedList?

Voglio essere sicuro di capirlo correttamente.

LinkedList::~LinkedList() 
{ 
    ListNode *ptr; 

    for (ptr = head; head; ptr = head) 
    { 
    head = head->next 
    delete ptr; 
    } 
} 

Così, all'inizio del ciclo, puntatore PTR è impostato per contenere l'indirizzo della testa, il primo nodo della lista. la testa viene quindi impostata sull'elemento successivo, che diventerà l'inizio dell'elenco una volta eseguita questa prima eliminazione. ptr è cancellato, e così è il primo nodo. Con la prima iterazione del ciclo, il puntatore viene reimpostato nuovamente.

La cosa che mi riguarda è raggiungere l'ultimo nodo. La condizione "testa"; dovrebbe verificare che non sia nullo, ma non sono sicuro che funzionerà.

Qualsiasi aiuto apprezzato.

+0

Perché non provare a eseguire il codice tramite un debugger per vedere se funziona? – Manuel

+0

@Manuel, perché i debugger su alcune piattaforme non sono integrati e sono difficili da usare? –

+2

so che mi faranno sparare per questo (qualcuno lo fa sempre, ma sono un beleiver). head è una variabile membro, dovresti davvero avere una convenzione di denominazione per le variabili membro, come m_head o head_ – pm100

risposta

15

Perché non farlo molto più semplice - con un elegante while -loop invece di cercare di analizzare attentamente se quello overcampillated for -loop è corretto?

ListNode* current = head; 
while(current != 0) { 
    ListNode* next = current->next; 
    delete current; 
    current = next; 
} 
head = 0; 
+1

ovviamente, questo funzionerà ... ma se il codice originale menzionato da OP funzionerà? – Naveen

+0

Devo notare che 'current' non cambia mai e' next' non è mai usato. Era pensato come un cattivo gioco di parole verso l'OP? –

+6

@ Matthieu M .: Nessun cattivo gioco di parole. Vorresti per favore approfondire "mai cambia" e "mai usato"? – sharptooth

3

La condizione di "testa"; dovrebbe verificare che non sia nullo, ma non sono sicuro che funzionerà.

Sì, "testa" di per sé è lo stesso di "testa = null!" - ma perché usare una scorciatoia di battitura significato se anche a trovarlo confusione? Sono solo altre 6 sequenze di tasti (e genera codice macchina identico), quindi scegli la forma lunga.

Inoltre, il codice è un po 'più complicato del necessario perché si utilizza un costrutto for(). Perché non utilizzare un while()? Il tuo codice sarà molto più pulito.

Infine, mi rendo conto che lo stai facendo come un esercizio di apprendimento, ma tieni presente che l'elenco <> si trova nella libreria standard. Gli elenchi collegati sono un "Problema risolto".

+0

Quello che volevo dire era che, visto che la testina potrebbe essere nulla, avrei avuto problemi con l'accesso a "next"? Da quanto ho capito, la testa puntava all'ultimo nodo, e l'accesso successivo conterrebbe null invece di un indirizzo al nodo successivo. – kevin

5

Puoi eseguirlo attraverso un debugger o puoi eseguirlo attraverso quel frammento di wetware all'interno del tuo cranio - entrambi ti mostreranno che funziona bene. Per esempio, cominciamo con l'elenco:

head(47) -> [47]single_node -> [NULL]end-of-list. 

esecuzione tale elenco attraverso le sue dichiarazioni:

  • ptr = head set ptr a 47.
  • head è diverso da zero in modo da entrare in loop.
  • head = head->next imposta head su NULL.
  • delete ptr eliminerà lo single_node.
  • ptr = head imposta ptr su NULL.
  • head ora è NULL (0) in modo da uscire dal ciclo.

Ecco fatto, hai eliminato l'unica voce nell'elenco e head ora è impostato su NULL. Questo è tutto ciò che devi fare.

È possibile fare una cosa simile con una lista più lunga o una lista vuota, troverete che è ancora a posto (non c'è una vera differenza tra un elenco di un elemento e un elenco di cinquanta elementi).

Per inciso, io non sono un grande fan di trattare puntatori come booleani - Preferirei lo scrivo come qualcosa di simile a:

for (ptr = head; head != NULL; ptr = head) 

rende il codice di leggere meglio a mio parere e don sacrificare davvero qualsiasi prestazione (a meno che tu non abbia un compilatore cerebrale). Ma è una questione di gusti.

Re tuo commento:

La cosa che mi preoccupa è di raggiungere l'ultimo nodo. La condizione "testa"; dovrebbe verificare che non sia nullo, ma non sono sicuro che funzionerà.

Funzionerà. Un valore pari a zero sarà trattato come falso, quindi scoprirai che non si può mai direzionare head-> next quando head è NULL semplicemente perché si è usciti dal corpo del ciclo prima di quel punto (o non è nemmeno entrato nel corpo se l'elenco è vuoto).

Qualsiasi altro valore del puntatore verrà considerato come true e sarà necessario immettere o continuare il corpo del loop.

0

Il codice potrebbe essere corretto, dovresti provare a eseguirlo con, ad es. Valgrind e vedi cosa dice. Tuttavia, vorrei scrivere in questo modo:

for (ListNode *current = head, *next; current; current = next) { 
    next = current->next; 
    free(current); 
} 
1

provato bene

distruttore per Lista classe

List::~List() 
{ 
    Node *n = this->front, *current = NULL; //initialization part 

    while(n)        //start cleanup of nodes of the list 
    { 
     current = n; 
     n=n->next; 
     delete(current); 
    } 

    front = end = NULL; 
} 
0

Questo è un approccio migliore per liberare/cancellazione della memoria utilizzando distruttore di un Linked -Elenco.

List()::~List() 
      { 
       for(Link* ptr= Head; Head; Head= Head->next) 
       { 
        delete ptr; 
       } 
      }