2010-02-15 10 views
12

Czy to jest poprawny destruktor listy łączy? Nadal jestem trochę zdezorientowany.Pisanie obiektu linkList destructor?

Chcę się upewnić, że rozumiem to poprawnie.

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

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

Tak więc na początku pętli, wskaźnik ptr jest ustawiony do przechowywania adresu głowy, pierwszego węzła na liście. head jest następnie ustawiony na następny element, który stanie się początkiem listy po tym pierwszym usunięciu. ptr jest usuwany, podobnie jak pierwszy węzeł. Przy pierwszej iteracji pętli wskaźnik ustawiany jest ponownie.

Rzeczą, która mnie niepokoi jest dotarcie do ostatniego węzła. Warunek "głowa" powinien sprawdzić, czy nie jest pusty, ale nie jestem pewien, czy to zadziała.

Każda pomoc doceniona.

+0

Dlaczego nie spróbować uruchomić kodu za pomocą debuggera, aby sprawdzić, czy działa? – Manuel

+0

@Manuel, ponieważ debuggery na niektórych platformach nie są zintegrowane i są trudne w użyciu? –

+2

Wiem, że zostanę postrzelony za to (ktoś zawsze to robi, ale jestem uważny). head jest zmienną składową, naprawdę powinieneś mieć konwencję nazewnictwa dla zmiennych członkowskich, jak m_head lub head_ – pm100

Odpowiedz

15

Dlaczego nie zrobić o wiele prostsze - z eleganckim while -loop zamiast próbować dokładnie przeanalizować, czy overcompilcated for -loop jest poprawna?

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

oczywiście, to zadziała ... ale czy oryginalny kod wspomniany przez OP będzie działał? – Naveen

+0

Należy zauważyć, że 'current' nigdy się nie zmienia, a' next' nigdy nie jest używany. Czy oznaczało to kiepskie kalamburowanie do OP? –

+6

@Matthieu M .: Żadne złe kalambury nie są zamierzone. Czy mógłbyś rozwinąć "nigdy się nie zmienia" i "nigdy nie używać"? – sharptooth

3

Warunek "głowa"; powinien sprawdzić, czy nie jest pusty, ale nie jestem pewien, czy to zadziała.

Tak, „głowa” sam jest taka sama jak „głowy! = Null” - ale dlaczego używać sensu wpisując skrót jeśli nawet okazać się mylące? To tylko 6 kolejnych naciśnięć klawiszy (i generuje identyczny kod maszynowy), więc idź do długiej formy.

Ponadto Twój kod jest nieco bardziej skomplikowany niż to konieczne, ponieważ używasz konstruktu for(). Dlaczego nie skorzystać z while()? Twój kod będzie znacznie czystszy.

Wreszcie, zdaję sobie sprawę, że robisz to jako ćwiczenie edukacyjne, ale pamiętaj, że lista <> jest w standardowej bibliotece --- Listy połączone są oficjalne "Rozwiązany problem".

+0

Co miałem na myśli, biorąc pod uwagę, że głowa może być zerowa, czy napotkam problemy z dostępem do "następnego"? Z tego co rozumiem, głowa wskazywałaby na ostatni węzeł, a dostęp do następnej zawierałby wartość zerową zamiast adresu do następnego węzła. – kevin

5

Można go uruchomić za pomocą debuggera lub można go uruchomić przez to trochę wetware wewnątrz czaszki - obie pokaże, że działa dobrze. Na przykład, zacznijmy z listy:

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

Uruchamianie tej listy poprzez swoje wypowiedzi:

  • ptr = head zestawy ptr do 47.
  • head jest niezerowe więc wprowadzić pętlę.
  • head = head->next ustawia head na NULL.
  • delete ptr usunie single_node.
  • ptr = head ustawia ptr na NULL.
  • head jest teraz NULL (0), więc zakończ pętlę.

W tym miejscu usunięto jedyny wpis z listy, a head jest teraz ustawiony na NULL. To wszystko, co musisz zrobić.

Możesz zrobić coś podobnego z dłuższą listą lub pustą listą, okaże się, że nadal jest w porządku (nie ma prawdziwej różnicy między listą jednoelementową a listą składającą się z pięćdziesięciu elementów).

Tak na marginesie, nie jestem wielkim fanem leczenia wskazówek jak logicznych - Wolałbym napisać go jako coś w rodzaju:

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

To sprawia, że ​​kod czytać lepiej moim zdaniem i don Naprawdę poświęcasz jakąkolwiek wydajność (chyba że masz nieumarły kompilator). Ale to kwestia gustu.

Re Twój komentarz:

Rzecz, która dotyczy mnie jest dotarcie do ostatniego węzła. Warunek "głowa" powinien sprawdzić, czy nie jest pusty, ale nie jestem pewien, czy to zadziała.

To zadziała. Wartość zero będzie traktowana jako fałsz, więc przekonasz się, że nigdy nie odrzucasz głowy-> dalej, gdy głowa ma wartość NULL, po prostu dlatego, że opuściłeś ciało pętli przed tym punktem (lub nawet nie wprowadziłeś ciała, jeśli lista jest pusta).

Każda inna wartość wskaźnika będzie traktowana jako prawdziwa, a użytkownik wprowadzi lub będzie kontynuował treść pętli.

0

Twój kod może być poprawny, powinieneś spróbować go uruchomić, np. valgrind i zobacz, co mówi. Chciałbym jednak napisać to tak:

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

Testowany OK

Destructor do listy klasy

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

Ten jest lepsze podejście do uwolnienia/kasowanie pamięci za pomocą destruktora wiązany -Lista.