c++ - 如何初始化作为结构指针的类成员

标签 c++ visual-studio class crash runtime

I have a problem with the application crashing at the line of code where if(!head) is being referenced inside the function: insertNode(). head and tail are class members of type node*. It looks like, I am missing something in the way the class members: head, tail are initialized.. This is the runtime error: "Unhandled exception at 0x00245246 in SLinkedlist_array.exe: 0xC0000005: Access violation reading location 0x00000000."


    slinkedlist.h:
    typedef struct node
    {
        int value;
        struct node* next;
    } node;

    class slinkedlist
    {
    public:
        //ctor, dtor, insertNode(int, int), displayList()
    private:
        node* head, tail;
    };

    slinkedlist.cpp:
    bool slinkedlist::insertNode(int value, int aftNodeVal)
    {
        int toinsertval = value;
        int searchkey = aftNodeVal;
        bool retval = false;

        // If it's a new linked list
        if(!head)  // THIS IS WHERE THE APPLICATION CRASHES!
        {
            node* head = new node;
            head->value = toinsertval;
            head->next = NULL;
            return true;
        }
        else //It's not a new list
        {
            while(head->next != NULL)
            {
                 //some more code here... 
            }
        }
        return retval;
    }

    void slinkedlist::displayList()
    {
        while(!head)
        {
            do
            {
                cout << head->value << " " ;
                head = head->next;
            }
            while(head->next != NULL);
        }
        //return void;
    }

    main.cpp:
    int main()
    {
        slinkedlist *s1 = NULL;
        s1->insertNode(4, -1);
        s1->displayList();
        while(1);
    }`

最佳答案

slinkedlist *s1 = NULL;

定义一个指向slinkedlist的指针并执行初始化操作不幸的是,它将其初始化为NULL,这是一个(通常)不允许存在任何对象的安全 parking 地址。对于绝大多数CPU(我曾经使用过的每个CPU),访问NULL附近的死区都会使程序崩溃,从而更容易检测错误。

这里不需要指针。如果不需要指针,请不要使用指针。您的生活会轻松得多。
int main()
{
    slinkedlist s1; // default initializes
    s1.insertNode(4, -1);
    s1.displayList();
    while(1); // rethink this. If you want to hold a program open to see the output 
              // while debugging, place a breakpoint in the debugger.   
}

单独使用s1Default initializing并不能帮助您,因为它将做绝对的最小工作来初始化其成员变量,并且在使用指针的情况下,最小的工作是不执行任何操作,并且不对headtail进行初始化和指向(而不是指向不确定位置的指针。因为您也没有在询问编译器错误,所以应该从将tail分配给NULL来得到,该程序显然没有初始化tail,并且我认为tail构造函数不会做很多事情。

旁注:如果您有一个不做任何事情(并且不需要做任何事情)的构造函数或析构函数,则将其保留,并让编译器生成适当的代码。不存在的代码(也不需要存在)没有错误。
class slinkedlist
{
public:
    //ctor, dtor, insertNode(int, int), displayList()
private:
    node* head, tail; // the * only applies to head.
};

可能
class slinkedlist
{
public:
    //ctor, dtor, insertNode(int, int), displayList()
private:
    node* head = nullptr;
    node* tail = nullptr;
};

如果要编译为最新(2011年或更新)的C++标准。您不需要构造函数,使用默认分配即可完成工作。您仍然需要一个析构函数以及一个复制构造函数和一个赋值运算符来满足The Rule of Three

在较旧的C++标准中,您需要使构造函数更智能
class slinkedlist
{
public:
    slinkedlist(): head(NULL), tail(NULL)
    {
    }
    //dtor, insertNode(int, int), displayList()
private:
    node* head; // I recommend splitting the definitions up. It makes the code easier 
                // to read and makes it harder to make mistakes.
    node* tail;
};

您仍然需要一个析构函数,一个复制构造函数和一个赋值运算符。

请注意,这也适用于slinkedlist。如果您动态分配节点并且未将node显式设置为值,则您将不知道next指向何处,以及所有类似的测试
while(head->next != NULL)

会严重失败。

关于c++ - 如何初始化作为结构指针的类成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61124785/

相关文章:

c++ - 放大 QGraphicsView 时如何保持 QPen 像素宽度相同

c# - 在 VS2012 中获取 TypeInitializationException,但不是 2010

二级类不可读的 C++ 私有(private)变量

c++ - 你用##称呼或术语宏是什么

c++ - 静态 QApplication 变量使 Mac 在退出时报告崩溃

c++ - boost.variant派生类型: cannot use copy constructor

php:使用反射获取变量类型提示

visual-studio - VS2010 执行单元测试(错误)

jquery - 有没有办法禁用某些异步回发的 UpdateProgress?

Java初始值?