【问题标题】:Singly Linked List - C++ - Unexplainable run-time error单链表 - C++ - 无法解释的运行时错误
【发布时间】:2013-10-28 06:28:51
【问题描述】:

我编写了以下代码,仅在 C++ 中创建节点(整数数据)并将其插入到 SLL 中。

#include <stdio.h>

class Node
{
    public:
        int data;
        Node * next;
        Node * first;
        Node() {}

        void insert(int dat)
        {
            Node * newnode = new Node();
            newnode->data=dat;
            newnode->next=NULL;
            if(first==NULL)
            {
                first=newnode;
            }
            else
            {
                Node *temp=first;
                while(temp->next!=NULL)
                { temp=temp->next; }
                temp->next=newnode;
            }
        }
};

int main()    
{
    Node * a=new Node();
    a->insert(12);
    return 0;
}

起初,我尝试将 Node 构造函数重写为 Node(int dat),并尝试对我在插入中创建的每个新节点 (data=dat, next=NULL) 进行初始化。 Insert 将使用 main 中的“dat”值调用,它会调用重载的 Node 构造函数以将数据初始化为 dat 和 NULL 旁边。这导致我的程序崩溃。

所以我取出了默认构造函数和重载构造函数,并对插入本身中的每个新元素进行了初始化。我的程序运行良好。但是,即使添加默认构造函数(如代码的第 10 行所示),我的程序也会崩溃。谁能告诉我为什么这两种情况都会发生?

谢谢。

【问题讨论】:

  • 上面的代码对我来说不会崩溃。那是给你带来问题的代码吗?
  • Paul Draper - 是的,我复制粘贴了它。我正在使用 Dev-C++ 4.9.9.2。如果我只删除第 10 行,即构造函数,它就可以工作。
  • 您真的希望在每个节点中都有一个first 指针吗?通常first 是单链表的成员,但不是节点的成员。除此之外,您永远不会初始化 first 并且比较 (first == NULL) 可能会触发或不会触发。
  • 好吧,如果它能让你感觉好些,那么它与 g++ 4.6.3 一起工作就好了:/
  • 你试过调试器吗?

标签: c++ constructor linked-list


【解决方案1】:

您的默认构造函数未初始化数据成员。所以这一行:

Node * a=new Node();

创建具有未初始化成员的节点,当您尝试添加节点时会导致问题。当您删除默认构造函数时,上述行(由于 new Node() 中的父代以及该类没有用户定义的构造函数的事实)导致所有成员的 value initialization,因此指针被初始化为 NULL ,你就会得到预期的行为。

如果省略括号:

Node * a = new Node;

数据成员将未初始化,就像你有一个什么都不做的默认构造函数一样。

正确的解决方案是修复默认构造函数以显式初始化所有成员。

Node() :data(0), next(nullptr), first(nullptr) {}

【讨论】:

    【解决方案2】:
    Node * a=new Node();
    

    创建一个新节点,运行其默认构造函数...

    Node() {}
    

    ...这没什么用 - 甚至没有初始化 datanextfirst

    因此,当您调用时...

    a->insert(12);
    

    ...它会尝试...

    if(first==NULL)
    

    ...它正在从未初始化的内存中读取,导致未定义的行为。在一次运行中,新创建的对象可能碰巧在其中有一个 0,另一次它可能没有,另一次它可能只是在尝试读取该值时崩溃。你继续用未初始化的数据做其他更糟糕的事情。

    更一般地说,当您遇到此类问题时,我建议您放入 std::cerr &lt;&lt; xyz &lt;&lt; '\n'; 语句以转储一些相关变量,或在调试器中进行跟踪 - 您可能已经看到变量具有垃圾值,然后可能已经开始调查原因,这可能会在此处产生更集中的问题,或者可能会引导您找到现有答案....

    【讨论】:

    • 我明白你在说什么,但如果我删除构造函数不应该发生同样的事情吗?我只是有没有初始化 first 的声明,我正在检查 if(first==NULL)。
    • @user2881037:本杰明已经解决了这方面的问题,所以我没有在这里添加解释。在他链接的维基百科页面中,请注意值初始化的这一方面:“如果T 是没有任何用户提供的构造函数的非联合类类型,则该对象为零初始化,然后调用隐式声明的默认构造函数(除非它是微不足道的)。”因此,在您的系统(实际上,几乎所有系统)上,零初始化指针恰好为 NULL。
    【解决方案3】:

    像这样在构造函数中初始化成员变量

    Node() {
                 data =0;
                 first = NULL;
                 next = NULL;
    }
    

    【讨论】:

    • 初始化列表将是更聪明的方法。 Node() : data(0), next(nullptr), first(nullptr) {}
    猜你喜欢
    • 2015-11-18
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    • 2016-01-01
    • 1970-01-01
    相关资源
    最近更新 更多