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
相关产品推荐
相关产品推荐

