2017-02-01 7 views
2

Я не новичок в программировании, но изучаю C++. Для этого я реализую «стандартные» структуры данных на языке C++. Я начинаю с Linked Lists. Я понимаю, как они работают и все такое. Однако, когда я пытаюсь распечатать список, он не останавливается, когда это предполагается. Я установил последний указатель на nullptr и все это и сильно исследовал эту проблему в Интернете, но я не могу найти то, что я делаю, отличное от всех остальных. Вот код:C++ Связанный список Печать Crash

template<typename T> 
void LinkedList<T>::print_list(){ 

    list_node<T> *pos = this->start; 

    while(pos != nullptr){ 
     cout << "PRInting" <<pos->data<<endl <<pos->next; 

     pos = pos->next; 
    } 
} 

Вот полный код:

#ifndef LINKEDLIST_H_INCLUDED 
#define LINKEDLIST_H_INCLUDED 

#include <iostream> 

using std::cout; 
using std::endl; 
template <class T> 
struct list_node{ 
    T data; 
    list_node<T> *next; 
}; 
template <class T> 
class LinkedList{ 
private: 
    list_node<T> *start; 

public: 
    LinkedList(); 
    LinkedList(T firstData); 
    ~LinkedList(); 
    void insert_item(T item); 
    void delete_item(T item); 
    list_node<T>* search_list(); 
    void print_list(); 
}; 



//constructors and destructor 
template <typename T> 
LinkedList<T>::LinkedList(){ 
    this->start = nullptr; 
} 
template <typename T> 
LinkedList<T>::LinkedList(T firstData){ 
    list_node<T> newNode = { 
     firstData, 
     nullptr 
    }; 
    this->start = &newNode; 
    cout <<"Constructor" <<this->start->data<<endl; 
} 
template <typename T> 
LinkedList<T>::~LinkedList(){ 
    this->start = nullptr; 
} 

//Debugging print function 
template<typename T> 
void LinkedList<T>::print_list(){ 
    list_node<T> *pos = this->start; 
    while(pos != nullptr){ 
     cout << "PRInting" <<pos->data<<endl <<pos->next; 
     pos = pos->next; 
    } 
    //cout << pos->data; 
} 


//Operations on Linked Lists 
template <typename T> 
void LinkedList<T>::insert_item(T item){ 
    list_node<T> *insertNode; 
    insertNode->data = item; 
    insertNode->next = this->start; 
    this->start = insertNode; 
    cout << "After insert " <<this->start->data << '\n' << this->start->next->data<<endl; 
} 

#endif // LINKEDLIST_H_INCLUDED 
+6

_I установить последний указатель на nullptr_ Мы не можем видеть, что из примера, приведенного. Пожалуйста, предоставьте [mcve]. –

+0

Эта функция выглядит хорошо для меня. Проблема, безусловно, в другом месте. –

+0

Если ваша последняя выводимая строка перед сбоем не равна 0, то у вас нет списка с нулевым завершением – user3853544

ответ

4

У вас есть 2 разные проблемы, касающиеся вставки узла, которые присутствуют в вашем коде.

  1. В конструкторе: Вы создаете локальную переменную newNode и сохранение его адреса памяти в this->start. Однако объект newNode будет уничтожен при выходе из области действия конструктора, и попытка разыменования приведет к UB (неопределенное поведение). Вы должны выделить узел динамически, так что он не будет уничтожен, как только он выходит из сферы:

    LinkedList<T>::LinkedList(T firstData){ 
        this->start = new list_node<T>; 
        this->start->data = firstData; 
        this->start->next = nullptr; 
        cout <<"Constructor" <<this->start->data<<endl; 
    } 
    
  2. В вашей insert_item процедуры: Вы разыменование локального указателя insertNode, несмотря на то, никакой фактическая память не была выделена для него , и разыменование его приводит к UB, а также. Правильный вариант будет выглядеть следующим образом:

    template <typename T> 
    void LinkedList<T>::insert_item(T item){ 
        list_node<T> *insertNode = new list_node<T>; 
        insertNode->data = item; 
        insertNode->next = this->start; 
        this->start = insertNode; 
        cout << "After insert " <<this->start->data << '\n' << this->start->next->data<<endl; 
        } 
    
  3. И теперь, поскольку мы делаем динамическое распределение памяти, мы должны освободить его в деструкторе (C++ не имеет сбора мусора), так просто присваивая start к nullptr не будет быть достаточно:

    template <typename T> 
        LinkedList<T>::~LinkedList(){ 
         list_node<T> *pos = this->start; 
         while (pos != nullptr){ 
          list_node<T>* nextPos = pos->next; 
          delete pos; 
          pos = nextPos; 
         } 
        } 
    
+0

Лучше, чем мой ответ, поэтому я собираюсь ответить с комментарием: вместо того, чтобы использовать фиктивный узел в качестве конца связанного списка, подумайте о том, чтобы вместо этого установить следующий элемент последнего узла «null_ptr» и проверить его. Меньшее количество используемого хранилища и одна меньшая итерация 'node-> next'. Простым способом начать с этого является добавление конструктора в 'list_node':' list_node (T & data): данные (данные), next (nullptr) {} 'Теперь каждый созданный узел имеет данные и начинает указывать на нет следующего узла, и вы можете пощекотать его в конце списка или в начале или в середине, не беспокоясь о том, что вы забыли завершить список. – user4581301

+0

Это работает. Благодарю. И, если я могу уточнить для себя. «Новое» ключевое слово динамически выделяет память. Если память не динамически распределена для объекта, она будет уничтожена после ее выхода из области видимости? – SH7890

+1

@ Shadow1356 у вас это получилось. Просто запомните 'delete', что вы' new'. [Умные указатели могут помочь с этим] (http://stackoverflow.com/questions/106508/what-is-a-smart-pointer-and-when-should-i-use-one) – user4581301

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