C++ C++;带有函数的自定义链表

C++ C++;带有函数的自定义链表,c++,function,pointers,linked-list,C++,Function,Pointers,Linked List,我实现了一个简单的链表。瞧 struct List{ List *next; bool last; string data; }; List *head; 然而,当我试图用一个函数构建它,然后遍历它时,程序崩溃了,错误为0x00005(这是内存错误,对吗?)。在build函数中,一切看起来都很好,但在其他方面它会抛出一个错误。下面是我列出的函数: void mkList(List *ptr, int num){ if(num != 0){ pt

我实现了一个简单的链表。瞧

struct List{
    List *next;
    bool last;
    string data;
};

List *head;
然而,当我试图用一个函数构建它,然后遍历它时,程序崩溃了,错误为0x00005(这是内存错误,对吗?)。在build函数中,一切看起来都很好,但在其他方面它会抛出一个错误。下面是我列出的函数:

void mkList(List *ptr, int num){
    if(num != 0){
        ptr = new List;
        ptr->data = "asd";

        if(num == 1)ptr->last = true;
            else ptr->last = false;

        mkList(ptr->next,num-1);
    }
}
我试图遍历列表的方法主要是:

int main(){
    mkList(head,5);

    List *ptr = head;

    while(!ptr->last){
        cout << ptr->data <<endl;
        ptr = ptr->next;
    }
    return 0;
}
intmain(){
名单(总目,5);
列表*ptr=头;
而(!ptr->last){
这一行的cout数据

mkList(ptr->next,num-1);
您正在传递一个悬空指针。它只指向任何地方。您实际上需要像中一样传递指针的地址

mkList(&ptr->next,num-1);
并重新定义你的函数

void mkList(List **ptr, int num);

但这相当疯狂,而且可以更容易地完成…

程序崩溃的原因在于以下代码:

ptr = new List;
ptr->data = "asd";
...
mkList(ptr->next,num-1); // <-- ptr->next is uninitialized !
其中,此链表中的最后一个元素是
next
设置为
NULL
的元素。标记最后一个元素不需要额外的数据成员(不需要
bool last

这将解决未定义的行为,但为了实际使程序按预期工作,您需要更改
void mkList(List*ptr,int num)
的原型,以将
ptr
作为指向
List
的指针,以便对指针本身所做的更改对调用者可见:

void mkList(List** ptr, int num) {
    if (num <= 0)
        return;

    *ptr = new List();
    (*ptr)->data = "asd";
    mkList(&(*ptr)->next, num-1);
}
尽管递归在这里不是最幸运的选择。保持简单是一个很好的做法,如果为了可读性,不要害怕写更多的代码行:

void mkList(List** ptr, int num)
{
    List* lastNode = NULL;
    for (int i = 0; i < num; ++i)
    {
        // create new node:
        List* node = new List();
        node->data = "asd";

        // store the pointer to the head:
        if (i == 0) *ptr = node;

        // move to the next element:
        if (lastNode) lastNode->next = node;
        lastNode = node;
    }
}
void mkList(列表**ptr,int num)
{
List*lastNode=NULL;
对于(int i=0;i数据=“asd”;
//存储指向头部的指针:
如果(i==0)*ptr=node;
//移动到下一个元素:
如果(lastNode)lastNode->next=node;
lastNode=节点;
}
}

我认为您需要重新访问指针的概念。 您需要了解指针是一个变量,它保存另一个变量的内存地址

如果您有这样的代码:

void foo(int a){
 a = 5;
}

// ...

int b = 0;
foo(b)
你不希望b在最后一行之后变成5,是吗? 指针也一样

void foo(List *a){
 a = new List;
}

// ...

List *b;
foo(b);
不会以任何方式影响b。现在,如果您想从另一个函数设置b的值,可以将指针传递给b(请记住,指针是一个变量,因此可以将指针传递给指针):


一旦您理解了这一点,就可以很容易地修复此代码。

遵循代码有点困难。您可以制作一个小的、完整的程序来复制错误吗?还有,为什么要使用数字6?我猜您正在尝试构建一个具有固定大小的列表,但这样的硬代码变量可能会很危险。好的,现在正在缩小代码。我还使用了六个,对于cout-s,这只是暂时的。如果在函数参数中给定一个指针,指针不是指向一个对象吗?我的意思是指针的副本应该指向同一个对象,对吗?>指针的副本应该指向同一个对象——这是正确的。但是,在您的示例中:1)指针你传递的不是指向任何特定的对象,因为它是未初始化的2)当你给指针赋值时,你只是在更改指针的值。指针指向的任何对象都不会受到影响。记住,指针只保留地址。当你更改指针时,你更改了它保留的地址,但是它所指向的对象保持不变。要实际更改它所指向的对象,您需要取消对指针的引用。另外,p->foo只是(*p).foo的缩写。我想这可能会帮助您理解。太棒了!这正是我需要的!谢谢!:)
void foo(int a){
 a = 5;
}

// ...

int b = 0;
foo(b)
void foo(List *a){
 a = new List;
}

// ...

List *b;
foo(b);
void foo(List **a){
 a = new List;
}

// ...

List *b;
foo(&b);
// now b will point to the newly allocated memory