C++ 链表:最后一个指针不为空

C++ 链表:最后一个指针不为空,c++,linked-list,singly-linked-list,C++,Linked List,Singly Linked List,我正在尝试在链表的开头插入一个条目,因此如果该列表之前为空,那么最后插入的节点的下一个节点显然应该为0/NULL。 我只是不明白为什么在我的代码中不是这样 我已经搜索了答案,但我能找到的只是将list->head设置为0,这是我在struct\u list中做的 list.cpp #包括 #包括 #包括“list.h” 结构节点 { 作废*数据; 节点*下一步; }; 结构列表 { 节点*head=nullptr; }; 列表*列表创建() { List*List=(List*)malloc(

我正在尝试在链表的开头插入一个条目,因此如果该列表之前为空,那么最后插入的节点的下一个节点显然应该为0/NULL。 我只是不明白为什么在我的代码中不是这样

我已经搜索了答案,但我能找到的只是将list->head设置为0,这是我在
struct\u list
中做的

list.cpp
#包括
#包括
#包括“list.h”
结构节点
{
作废*数据;
节点*下一步;
};
结构列表
{
节点*head=nullptr;
};
列表*列表创建()
{ 
List*List=(List*)malloc(sizeof(List));
list->head=nullptr;
退货清单;
}
作废列表\添加(列表*列表,作废*数据)
{
Node*current=(Node*)malloc(sizeof(Node));
当前->数据=数据;
当前->下一步=列表->标题;
列表->头部=当前;
}

对不起,你完全错了。这就是它应该是什么样子

//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;
}

malloc分配内存。它不调用构造函数。因此,这将导致为“列表类型”分配内存,但它将包含未初始化的垃圾

Node *current = (Node *)malloc(sizeof(Node));
但是现在这还可以,因为你需要初始化所有的东西

current->data = data;
current->next = list->head;
[删除了我教您如何使用对象进行可维护性封装的部分]

现在让我们看看您的列表类型:

struct List
{
    Node *head = 0;
};
类(struct)声明中的默认值应用于任何构造函数。但是malloc不是构造函数,也不调用构造函数。它只是获得了所需的内存。因此,如果您使用malloc sizeof(List),您将不会得到任何初始化

然而,你甚至不这样做。您可以为指向列表的另一个指针分配空间。因此,list_create为您提供了一个指向某个已分配内存的指针,另一个指向随机垃圾的指针(它不是一个列表,如果已分配,它也将无效)。虽然我认为sizeof(List)和sizeof(List*)在编译器上可能是相同的,但如果你运气好的话,那就太好了

return  (List *)malloc(sizeof(List *));
你本想这么做的

List * list = (List *)malloc(sizeof(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
intmain(){
List*List=List_create();
列表\添加(列表,空PTR);

STD: > NeX<代码> MalOC/不做任何分配内存(包括初始化它为零),所以你的代码> ListsCREATECREX/OCKE>创建一个列表,它的定义不明确,代码“> <代码>。你应该手动将它归零。我怀疑你实际上是使用C++编译器,因为默认值是C++允许的。(但不应该使用C函数来分配数据)1。前缀<代码>代码< >代码>是为编译器实现保留的。2。您从不初始化< <代码>节点> <代码> > <代码>数据>代码>代码>下< /COD>,因此您不必怀疑。您在C++中,使用对象!您是否在ListSueCube中分配了一个指针,因此指针指向无效指针。(它错误地认为这是一个无效的列表)?构造函数会容易得多。另外,您应该发布一个很短的main来说明问题,因此这是一个不能有无效数据的问题。List::create()应该是List::List()添加前的一个冒号是语法错误。列表::添加不带参数,因此节点不应包含数据。我知道您在首次引入对象时试图避免使用模板,但可能希望调整方法。数据实际上是一个空*在OPYes中,我知道我认为它是一个占位符,用于将问题概括:)我从来没有使用过那种数据类型,但是你可以用int,double,bool,char来代替void。我试图帮助你解决实际的错误。还有语法错误……顺便说一句,“new”调用一个构造函数,所以NeX/DELL比MalC/C++好,但是在现代C++中仍然是坏的,除非完全封装在你的类中。所以你可以在节点上使用Neal/Delphi,但是你的问题是列表没有被构建。code>list\u create
但这并没有改变任何东西(是的,我将
sizeof(list*)
更改为
sizeof(list)
)。当我在调试器中运行它时,它似乎修复了“为什么它没有初始化?”问题。
list->head = nullptr; // we're supposed to use "nullptr" now for type safety
return list;
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