【问题标题】:C++ pointer arithmetic for linked lists链表的 C++ 指针算法
【发布时间】:2022-11-21 19:52:29
【问题描述】:

我刚刚开始自学 C++,作为一个玩具问题,我正在尝试执行以下操作 - 给定一个链表,我想将所有节点存储到一个新列表中,并返回这个新列表。对于上下文,我来自 Python 背景。

我有以下程序 -


#include <iostream>
using namespace std;

struct node
{
    unsigned val;
    struct node *next;
};

node *even_nodes(node **root)
{
    node *new_list_head = NULL;
    node *new_list_runner = NULL;
    node *runner = *root;
    while (runner != NULL)
    {
        if (new_list_head != NULL){
            printf("OUTSIDE LOOP new_list_head.val = %d\n", new_list_head->val);
        }
        if (runner->val % 2 == 0)
        {
            cout << runner->val << endl;
            node new_node = {.val = runner->val, .next = NULL};
            if (new_list_head == NULL)
            {
                printf("new_list_head is NULL!\n");
                new_list_head = &new_node;
                new_list_runner = &new_node;
                printf("after allocation. new_list_head.val = %d\n", new_list_head->val);
            }
            else
            {
                printf("new_list_head is NOT NULL! new_list_head.val = %d\n", new_list_head->val);
                new_list_runner->next = &new_node;
                new_list_runner = new_list_runner->next;
                printf("after allocation. new_list_head.val = %d\n", new_list_head->val);
            }
        }
        runner = runner->next;
    }
    printf("new_list_head val = %d\n", new_list_head->val);
    return new_list_head;
};

void add_data(node **root, int new_data)
{
    node *new_node = (node *)malloc(sizeof(node *));
    new_node->val = new_data;
    new_node->next = (*root);
    (*root) = new_node;
}

void print_list(node *root)
{
    node *head = root;
    while (head != NULL)
    {
        printf("%d -> ", head->val);
        head = head->next;
    }
    printf("END\n");
};

int main()
{
    node *head = NULL;
    add_data(&head, 19);
    add_data(&head, 18);
    add_data(&head, 3);
    add_data(&head, 4);
    add_data(&head, 1);
    printf("Initial list:\n");
    print_list(head);
    node *new_list = even_nodes(&head);
    printf("New list of even numbers: \n");
    print_list(new_list);

    return 0;
}

输出如下 -

Initial list:
1 -> 4 -> 3 -> 18 -> 19 -> END
4
new_list_head is NULL!
after allocation. new_list_head.val = 4
OUTSIDE LOOP new_list_head.val = 4
OUTSIDE LOOP new_list_head.val = 4
18
new_list_head is NOT NULL! new_list_head.val = 18
after allocation. new_list_head.val = 18
OUTSIDE LOOP new_list_head.val = 18
new_list_head val = 18
New list of even numbers: 
[1]     segmentation fault 

我不明白为什么new_list_head也随着new_list_runner而变化?为什么我的new_list_head 指向新列表的最后一个元素,而不是第一个?

另外,为什么会出现段错误?在print_list方法中,为什么守卫

while (head != NULL)

不工作?

任何帮助将不胜感激!

【问题讨论】:

  • 使用 node new_node = ...; 你定义了一个当地的多变的。一个变量,其生命周期将在当前块结束时结束,这意味着该变量将不复存在。您使用 &amp;new_node 获得的指针将变得无用,并且任何取消引用该指针的尝试都将导致未定义的行为.请刷新您的教科书或教程范围寿命.
  • 感谢您的回复!这对我帮助很大。似乎我改变了以下行 -

标签: c++ pointers linked-list


【解决方案1】:

您不能通过获取局部变量的地址来进行动态分配。当作用域退出时,局部变量被销毁,你留下一个指向不存在的对象的指针(称为悬空指针)。

你的代码在这里有这个问题

node new_node = {.val = runner->val, .next = NULL}; // local variable
if (new_list_head == NULL)
{
    new_list_head = &new_node; // BAD
    new_list_runner = &new_node; // BAD
}
else
{
    new_list_runner->next = &new_node; // BAD
    new_list_runner = new_list_runner->next;
}

相反,您应该使用new 来分配新节点,使用new 创建的对象在您delete 之前不会被销毁。

node* new_node = new node{runner->val, NULL};
if (new_list_head == NULL)
{
    new_list_head = new_node;
    new_list_runner = new_node;
}
else
{
    new_list_runner->next = new_node;
    new_list_runner = new_list_runner->next;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    • 2011-04-01
    • 1970-01-01
    • 2018-07-28
    • 2013-08-07
    相关资源
    最近更新 更多