【问题标题】:singly linked list c++ constructor, destructor and printing out单链表 C++ 构造函数、析构函数和打印输出
【发布时间】:2019-05-14 20:18:48
【问题描述】:

我是一个学习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;
}

我在运行构造函数时不断出现分段错误,但我不明白为什么。我在哪里犯错?任何帮助将不胜感激!

【问题讨论】:

  • 第一个跳出来的明显错误是:if(head == NULL) { head-&gt;next = node; ...
  • 为什么这是一个错误?我写了这段代码,因为只有在 head 和 node 之间建立的第一个链接应该是这样,其他的应该以其他方式放置。
  • 想一想:如果headNULL,那么当您尝试将某些内容分配给head-&gt;next 时会发生什么?
  • head-&gt;next 对 Erica 意味着什么?
  • |数据 |下一个 |说如果这是头,head-&gt;next 将表示它链接到的内容,即下一个节点。但是head不会被初始化为NULL吗?

标签: c++ list linked-list singly-linked-list


【解决方案1】:

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

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
}

【讨论】:

  • 哇,这真的很有帮助!如果我做对了,那么在这个 for 循环完成后,最后一个节点将指向 null?我理解你的代码吗?
  • @Erica 不,直接在循环之后,最后一个节点的next 指针仍然未初始化。这就是为什么我们还需要显式分配空指针的原因。
  • 1.假设我们有n_nodes == 0。然后根本不会进入循环,tmp 仍然指向head(即*tmp == head)。然后赋值 after 循环会将 head 初始化为 nullptr(间接地,通过 tmp 指针)。 2.n_nodes != 0会进入循环。然后在第一个循环运行中,head 将直接分配新节点(之前没有分配 nullptr,这无关紧要,无论如何这个分配都会丢失......)。
  • 假设头指针一开始就指向一个我们称之为garbage的值。我们现在可以0 开始覆盖这个garbage。如果循环进入,这个0会被e覆盖。 G。 0x1012 假设节点是在那里创建的。如果没有进入循环,那么,作为*tmp == head,我们将分配head 0再次。所以对0 的初始分配是徒劳的。这就是我想要表达的... tmp 指针在退出构造函数后丢失 - 但通过此指针所做的更改仍然存在!
  • 比较以下:int n, m; int* p = &amp;n; *p = 10; p = &amp;m; *p = 12; - 现在nm 的值是什么?我在我的代码中没有做任何不同的事情,只是 nm 的类型本身就是指针,我没有分配整数文字,而是地址。就是这样。
猜你喜欢
  • 2016-12-28
  • 2021-07-20
  • 2011-04-03
  • 2010-12-16
  • 1970-01-01
  • 2020-08-16
  • 2012-04-10
  • 2012-11-14
  • 2016-09-09
相关资源
最近更新 更多