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

时间:2013-04-03 19:52:39

标签: c++ function pointers linked-list

我实现了一个简单的链表。看哪!

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

List *head;

但是,当我尝试使用函数构建它,然后遍历它时,程序崩溃并出现错误0x00005(这是一个内存错误,对吧?)。在构建函数中一切似乎都很好,但否则会引发错误。这是我列出的功能:

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

我尝试遍历列表的方法是main:

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

    List *ptr = head;

    while(!ptr->last){
        cout << ptr->data <<endl;
        ptr = ptr->next;
    }
    return 0;
}
一切似乎都工作正常,直到第二个元素,我甚至可以cout第一个元素的数据!我做错了什么?

3 个答案:

答案 0 :(得分:0)

在这一行

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

那样传递指针的地址
mkList(&ptr->next,num-1);

并将您的功能重新定义为

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

但这很疯狂,可以更轻松地完成......

答案 1 :(得分:0)

您的程序崩溃的原因是在此代码中:

ptr = new List;
ptr->data = "asd";
...
mkList(ptr->next,num-1); // <-- ptr->next is uninitialized !

您使用未初始化的变量ptr->next,它会产生 未定义的行为 。可能的解决方案是为struct定义默认构造函数:

struct List{
    List() : next(NULL) { }
    List *next;
    string data;
};

此链接列表中的最后一个元素是next设置为NULL的元素。您不需要额外的数据成员来标记最后一个元素(您不需要bool last)。

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

List

void mkList(List** ptr, int num) { if (num <= 0) return; *ptr = new List(); (*ptr)->data = "asd"; mkList(&(*ptr)->next, num-1); }

这样调用
main

虽然递归不是这里最幸运的选择。 保持简单 是一种很好的做法,如果是为了便于阅读,不要害怕编写更多代码行:

mkList(&head, 5);

答案 2 :(得分:0)

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

如果你有这样的代码:

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(记住,指针是一个变量,所以指向一个指针是完全没问题的。指针):

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

// ...

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

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