2012-05-26 3 views
1

Я только что реализовал Связанный список. Он работает отлично, но даже жестко я видел нотацию. Я не могу создать рабочий деструктор на узле, поэтому он не реализован здесь в коде.Список деструкторов в C++

  1. Мне нужно реализовать рабочий деструктор на узле
  2. деструктор Список но это один простой, я просто использовать деструктор из класса Node (но мне нужно это).
  3. Сделать список удобным для узла, поэтому мне не нужно будет использовать getNext(), но я думаю, что могу справиться с этим сам (не знаю, как, но я узнаю).

Пожалуйста, посмотрите на код, это прекрасно, просто сработает, если вы его скопируете.

#include <cstdio> 
#include <cmath> 
#include <iostream> 
#include <stdio.h> 
#include <string.h> 
using namespace std; 

class Node { 
public: 
    Node(Node* next, int wrt) { 
     this->next = next; 
     this->wrt = wrt; 
    } 

    Node(const Node& obiekt) { 
     this->wrt = obiekt.wrt; 
     this->next = obiekt.next; 
    } 
    ~Node() {} 

    void show() { 
     cout << this->wrt << endl; 
    } 

    int getWrt(){ 
     return this->wrt; 
    } 

    Node* getNext(){ 
     return this->next; 
    } 

    void setNext(Node* node){ 
     this->next = node; 
    } 

private: 
    Node* next; 
    int wrt; 
}; 

class List{ 
public: 
    List(int wrt){ 
     this->root = new Node(NULL, wrt); 
    } 

    List(const List& obiekt){ 
     memcpy(&this->root,&obiekt.root,sizeof(int)); 
     Node* el = obiekt.root->getNext(); 
     Node* curr = this->root; 
     Node* next; 
     while(el != NULL){ 
      memcpy(&next,&el,sizeof(int)); 
      curr->setNext(next); 
      curr = next; 
      next = curr->getNext(); 
      el = el->getNext(); 
    /*  curr->show(); 
      next->show(); 
      el->show(); */ 
     } 
    } 

    void add(int wrt){ 
     Node* node = new Node(NULL, wrt); 
     Node* el = this->root; 
     while(el->getNext() != NULL){ 
      //el->show(); 
      el = el->getNext(); 
     } 
     el->setNext(node); 
    } 

    void remove(int index){ 
     Node* el = this->root; 
     if(index == 0){ 
      //deleting old one 
      this->root = this->root->getNext(); 
     } 
     else{ 
      int i = 0; 
      while(el != NULL && i < index - 1){ 
      // el->show(); 
       el = el->getNext(); 
       i++; 
      } 
      if(el!=NULL){ 
       Node* toRem = el->getNext(); 
       Node* newNext = toRem->getNext(); 
       el->setNext(newNext); 
       //deleteing old one 
      } 
     } 
    } 

    void show(){ 
     Node* el = this->root; 
     while(el != NULL){ 
      el->show(); 
      el = el->getNext(); 
     } 
    } 

    ~List(){} 

private: 
    Node* root; 
}; 

int main(){ 
    List* l = new List(1); //first list 
    l->add(2); 
    l->add(3); 
    l->show(); 
    cout << endl; 

    List* lala = new List(*l); //lala is second list created by copy cosntructor 
    lala->show(); 
    cout << endl; 

    lala->add(4); 
    lala->remove(0); 
    lala->show(); 

    return 0; 
} 
+1

Вы не должны быть 'memcpy'-ки' Node's, поскольку они не являются объектами POD. –

+1

Я бы начал с исправления отступов и переименования переменных из 'n',' n2', 'wrt',' lala' в имена, имеющие какое-то значение. А также избавиться от 'using namespace std;' - это плохая практика, чтобы поместить его в начало такого файла. – LihO

+0

Нет, это не домашнее задание. Я пытаюсь обновить свой C++. n прокомментированы, я удалю их сейчас. – Yoda

ответ

1

Предлагаю вам начать с внедрения деструктора List. Поскольку вы динамически выделяете память с помощью new, вы должны освободить ее, используя delete. (Если вы использовали new[], было бы delete[]):

После того, как у вас есть надлежащее деструктор, вы должны попробовать, правильно ли ваш конструктор копирования:

List* lala = new List(*l); 
delete l; // delete list that was used to create copy, shouldn't affect copy 

вы обнаружите, что ваш конструктор копирования неверно, а также приводит к сбою вашего приложения. Зачем? Поскольку цель copy constructor заключается в создании объекта нового в качестве копии существующего объекта. Ваш экземпляр копии просто копирует указатели, если sizeof(Node*) равен sizeof(int). Он должен выглядеть следующим образом:

List(const List& list) 
{ 
    // if empty list is being copied: 
    if (!list.root) 
    { 
     this->root = NULL; 
     return; 
    } 

    // create new root: 
    this->root = new Node(NULL, list.root->getWrt()); 

    Node* list_currentNode = list.root; 
    Node* this_currentNode = this->root; 
    while (list_currentNode->getNext()) 
    { 
     // create new successor: 
     Node* newNode = new Node(NULL, list_currentNode->getNext()->getWrt()); 
     this_currentNode->setNext(newNode); 
     this_currentNode = this_currentNode->getNext(); 
     list_currentNode = list_currentNode->getNext(); 
    } 
} 

Кроме того, ваша функция remove неправильно, так как он «не снимает» ссылка на какой-то узел, но никогда не освобождает память, где этот узел находится. delete следует вызвать, чтобы освободить эту память.

«Мне нужно реализовать рабочий деструктор на узле» - Нет, вы не знаете. Сам узел не выделяет никакой памяти, поэтому он не должен освобождать память. Узел не должен нести ответственность за уничтожение Node* next или чистую память, где он хранится. Не используйте деструктор и конструктор копирования узла.Вы также хотите прочитать: What is The Rule of Three?

«Сделать список дружественной к узлу, так что я не должен использовать GetNext()» - Вы хотите сказать, в классе Node, что class List является его friend:

class Node 
{ 
    friend class List; // <-- that's it 

Обратите внимание, что из этих 5 заголовков, в которые включен код, требуется только один: <iostream>. Также обратите внимание, что запись using namespace std; в начале файла считается неправильной практикой, так как это может привести к неоднозначности имен некоторых ваших типов. Используйте его с умом в небольших областях или вместо этого используйте префикс std::.

+2

На самом деле было бы лучше определить 'Node' как внутреннюю частную структуру в' List'. Тогда вы можете избежать использования 'friend'. – betabandido

+0

Я действительно благодарю Тебя за то, что поделился этим знанием со мной. Кстати, вы представили его мне, я предполагаю, что вы, вероятно, были бы хорошим учителем (академиком). Отлично. – Yoda

+0

@RobertKilar: Я рад, что это помогло вам :) – LihO

1

Связанный список деструктор будет называться либо когда delete используются с ранее выделенным указателем на связанный список или когда связанный список переменных выходит из области видимости (например, локальные переменный разрушаются при выходе из функция).

Деструктор для связанного списка должен нести ответственность за освобождение памяти, которую вы ранее зарезервировали для узлов (то есть, используя операцию add). Итак, в основном, вам нужно пройти список узлов и применить операцию delete для каждого из них. Существует небольшая уловка: когда вы собираетесь удалить узел, вы должны быть осторожны, чтобы не потерять указатель на следующий элемент (когда узел удален, вы не можете быть уверены, что член next будет по-прежнему действителен).

0

Если вы хотите создать деструктор для своего узла, он должен быть довольно простым на самом деле.

Здесь:

class Node { 
    private: 
     int wrt; 
     Node* next; 
    public: 
     Node(Node* next, int wrt) { 
      this->next = next; 
      this->wrt = wrt; 
     } 

     // Your desired destructor using recursion 
     ~Node() { 
      if (next != NULL) 
       delete next; 
     } 
}; 

Это так просто :)

В принципе, перед узел будет удален, если рядом не пуст, мы удаляем следующий, который будет снова вызвать деструктор next, а если next-> next не пуст, снова деструктор вызывается снова и снова.

Затем в конце все Узлы удаляются.

Рекурсия заботится о целом вещь :)

+0

Я думаю, что это вызовет переполнение стека для большого списка из-за рекурсивных вызовов деструктора. – jbcoe

Смежные вопросы