You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++链表指针行为异常及反转后原指针失效的问题排查与解决

问题分析与解决方案

核心问题

你遇到的是典型的指针传递误区:函数接收的是指针的副本(所以pprint和reverse里的head指针值都和原指针a一致),但通过这个指针可以直接修改它指向的内存对象——也就是链表节点的next成员。reverse函数在反转过程中,把原头节点a的next改成了nullptr,直接破坏了原链表的结构,导致第三次调用pprint(a)只能输出第一个节点。

而pprint只是读取节点的val,没有修改任何节点成员,所以原链表结构不受影响。

如何保证传入函数的链表不被修改?

分两种场景处理:

1. 函数本身不需要修改链表(比如打印):用const限定指针

把函数参数声明为const Node* head,编译器会强制阻止函数内修改指针指向的节点成员。比如pprint的正确写法:

void pprint(const Node* head) {
    while (head) {
        cout << head->val << " ";
        head = head->next; // 仅修改指针副本的值,合法
        // head->next = ...; 这类修改节点成员的代码会直接编译报错
    }
    cout << endl;
}

这种方式能从编译层面保证函数不会改动原链表结构。

2. 函数需要修改链表但要保留原链表(比如反转):复制原链表再操作

如果需要反转后原链表仍能正常使用,绝对不能直接在原链表上修改。必须先创建原链表的完整副本,再反转这个副本,原链表就不会被触动。

示例代码:

// 复制链表的函数
Node* copyList(const Node* head) {
    if (!head) return nullptr;
    Node* newHead = new Node(head->val);
    Node* curr = newHead;
    const Node* origCurr = head->next;
    while (origCurr) {
        curr->next = new Node(origCurr->val);
        curr = curr->next;
        origCurr = origCurr->next;
    }
    return newHead;
}

// 反转链表的函数(操作副本)
Node* reverse(Node* head) {
    Node* prev = nullptr;
    Node* curr = head;
    while (curr) {
        Node* nextTemp = curr->next;
        curr->next = prev;
        prev = curr;
        curr = nextTemp;
    }
    return prev;
}

// 使用方式
Node* reversedList = reverse(copyList(a));
pprint(reversedList); // 打印反转后的链表
pprint(a); // 原链表结构完整,可正常打印

补充说明

别混淆两种const指针的作用:

  • const Node* head:指针指向的节点对象不能被修改,但指针本身可以移动(比如head = head->next)
  • Node* const head:指针本身不能被修改(不能移动到下一个节点),但指向的节点对象可以修改
  • const Node* const head:指针本身和指向的对象都不能修改

根据需求选择对应的限定方式即可。

内容的提问来源于stack exchange,提问作者dumb programmer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 17:02:23