我试图在链接列表的开头插入一个条目,因此,如果列表之前为空,则最后插入的节点的下一个显然应该为0 / NULL。 我只是不知道为什么我的代码中不是这种情况。
我已经搜索了答案,但我只能找到将list-> head设置为0的方法,就像我在struct _list
中所做的那样。
#include <stdlib.h>
#include <stdio.h>
#include "list.h"
struct _node
{
void *data;
Node *next;
};
struct _list
{
Node *head = nullptr;
};
List *list_create()
{
List *list = (List *)malloc(sizeof(List));
list->head = nullptr;
return list;
}
void list_add(List *list, void *data)
{
Node *current = (Node *)malloc(sizeof(Node));
current->data = data;
current->next = list->head;
list->head = current;
}
答案 0 :(得分:1)
malloc分配内存。它不调用构造函数。因此,这将导致为“ list_type”分配内存,但其中将包含未初始化的垃圾。
Node *current = (Node *)malloc(sizeof(Node));
但是现在还可以,因为您可以通过初始化所有内容来进行后续操作。
current->data = data;
current->next = list->head;
[已删除的部分,我在其中为您介绍了如何使用封装对象来实现可维护性]
现在让我们看看您的列表类型:
struct List
{
Node *head = 0;
};
类(结构)声明中的默认值适用于任何构造函数。但是malloc既不是构造函数,也不调用构造函数。它只是获得所需的内存。因此,如果您分配sizeof(List),将不会得到任何初始化。
但是,您甚至没有这样做。您为另一个指向列表的指针分配空间。因此,list_create为您提供了指向已分配内存的一个指针,而另一个指针则指向了随机垃圾(它不是List,如果分配了它也将无效)。尽管我认为在编译器上有可能sizeof(List)和sizeof(List *)相同,但是如果您很幸运的话,它就是UB。
return (List *)malloc(sizeof(List *));
您打算这样做
List * list = (List *)malloc(sizeof(List));
所以现在您有了一个列表大小的东西,然后必须添加它(因为您没有使用构造函数,默认或其他方式):
list->head = nullptr; // we're supposed to use "nullptr" now for type safety
return list;
但是您没有那个。您只需返回无效的指针。这就是该函数中的两个错误。
[已删除部分,我在其中教您如何使用对象。您可以从Samed Kahyaoglu的答案中获得答案。但是基本上,您必须通过构造函数或默认构造函数才能在类的标头声明中使用该默认值。]
证明头已初始化:
int main() {
List * list = list_create();
list_add(list, nullptr);
std::cout << list->head->next << std::endl;
}
output before fix:
CDCDCDCD
output after fix:
00000000
我的编译器在调试版本中使用CDCDCDCD初始化了malloc分配的数据,以便于发现未初始化的数据。发行版本可能只有以前存在的任何垃圾。
答案 1 :(得分:0)
对不起,你是完全错误的。这就是它的外观;
//first, define DataType or change DataType as you want to use
struct Node
{
DataType data;
Node* next;
};
struct List
{
Node *head;
void create();
void add();
};
void List::create()
{
head = NULL;
}
void List:add(DataType data)
{
Node* newNode = new Node;
newNode -> data = data;
newNode -> next = NULL;
Node* traverse = head;
while(traverse){
traverse->next; } // goes till finding last node then goes its next which is null
traverse = newNode;
return;
}