单链表c++构造函数、析构函数和打印

singly linked list c++ constructor, destructor and printing out

本人初学c++,目前正在做单链表。我遇到了一些问题,我想了很长时间,搜索了很多但仍然没有这个代码的答案所以我请求一些帮助..

所以这是我的 linked.h

template <class T>
class Node {
    public:
        T data;
        Node<T>* next;
};

template <class T>
class List {
    private:
        Node<T> *head;
    public:
        List() : head(NULL) {};
        ~List() {
            Node<T>* ptr, tmp;
            for(ptr = head->next; ptr == NULL; ptr = head->next) {
                delete ptr;
            }     
        }
        List(T* arr, int n_nodes) {
            head = NULL; 
            Node<T> *tmp = head;
            for(int i = 0; i < n_nodes; i++) {
                Node<T>* node = new Node<T>;
                node->data = arr[i];
                if(head == NULL) {
                    head->next = node;
                    tmp = node;
                }
                else {
                    tmp->next = node;
                    node->next = NULL;
                    tmp = node;
                }
            }
        }
        friend std::ostream& operator<<(std::ostream& out, List<T>& rhs) {                                                                                                                                 
            Node<T>* cur = rhs.head;
            out << cur;
            while(cur != NULL) {       
                if(cur->next != NULL) { 
                    out << cur->data << ", ";
                    cur = cur->next;
                }
                else
                    out << cur->data << " ";
            }
            return out;
        }
}; 

这是我的 main.cc 文件。

#include <iostream>
#include "linked.h"

int main() {
    int array[5] = {12, 7, 9, 21, 13};
    List<int> li(array, 5);
    std::cout << li;

    return 0;
}

当 运行 构造函数时,我一直遇到分段错误,但我不明白为什么。我在哪里犯了错误?如有任何帮助,我们将不胜感激!

你可以用指向指针的指针来解决这个问题:

List(T* arr, int n_nodes)
{
    Node<T>** tmp = &head; // tmp *pointing* to uninitialized(!) head pointer
    for(int i = 0; i < n_nodes; i++)
    {
        Node<T>* node = new Node<T>();
        node->data = arr[i];
        // now the trick:
        *tmp = node; // !!!
        // you now have assigned the new node to whatever pointer
        // the tmp pointer points to - which initially is - guess - head...

        // but we now need to advance!
        tmp = &node->next;
    }
    // tmp now points to latestly created node's next pointer
    // (or still head, if no nodes where created because of n_nodes == 0)
    // be aware that this one still is not initialized! so:
    *tmp = nullptr;
}

你的析构函数也必然会失败:

Node<T>* ptr, tmp;
for(ptr = head->next; ptr == NULL; ptr = head->next)
{
    delete ptr; // you delete ptr, but advancing (ptr = head->next)
                // is done AFTERWARDS, so you'd access already deleted memory
                // undefined behaviour
}

此外,您没有删除头节点!如果 head 是 nullptr,你又会有未定义的行为。

这样试试:

while(head)
{
    Node<T>* tmp = head; // need a copy of pointer
    head = head->next;   // need to advance BEFORE deleting
    delete tmp;          // now can delete safely
}