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.
}
单独使用
s1
的Default initializing并不能帮助您,因为它将做绝对的最小工作来初始化其成员变量,并且在使用指针的情况下,最小的工作是不执行任何操作,并且不对head
和tail
进行初始化和指向(而不是指向不确定位置的指针。因为您也没有在询问编译器错误,所以应该从将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/