C++指针结合封装的使用问题:自定义链表类异常求助
问题分析与修复方案
核心问题1:悬垂指针(最致命)
你的LinkedList构造函数里的Node n(-1)是局部变量,构造函数执行完毕后,这个变量会被销毁,内存被系统回收。此时Head和Current指向的是已经失效的内存地址,属于悬垂指针,后续所有对这些指针的操作都是未定义行为——这就是程序异常的根本原因。
另外,构造函数里的Head, Current = &n;写法逻辑错误:C++的逗号运算符会先执行左侧表达式,但这里只是对Head求值,并没有赋值,实际只有Current被赋值为&n,Head还是初始的NULL。
核心问题2:display函数逻辑错误
就算指针问题解决,display的逻辑也有问题:初始curr = Head后直接判断curr->Next != NULL,会跳过头节点的输出;如果Head是NULL,访问curr->Next还会直接触发崩溃。
修复后的完整代码
#include <iostream> using namespace std; class Node { public: int value; Node* Next = nullptr; // 用nullptr替代NULL,C++11及以上更安全 Node(int Value) : value(Value), Next(nullptr) // 初始化列表写法更规范 { } }; class LinkedList { public: Node* Head = nullptr; Node* Current = nullptr; int count = 0; LinkedList() { // 用动态分配创建头节点,避免局部变量销毁导致的悬垂指针 Head = new Node(-1); Current = Head; } // 实现尾插法添加节点 void pushNode(int value) { Node* newNode = new Node(value); Current->Next = newNode; Current = newNode; count++; } void display() { Node* curr = Head; cout << "HEAD->"; // 跳过哨兵头节点,从第一个有效节点开始遍历 curr = curr->Next; while (curr != nullptr) { cout << curr->value << "->"; curr = curr->Next; } cout << "NULL" << endl; } // 手动释放堆内存,避免内存泄漏(C#有GC自动回收,C++需手动管理) ~LinkedList() { Node* curr = Head; while (curr != nullptr) { Node* temp = curr; curr = curr->Next; delete temp; } } }; int main() { LinkedList ml; ml.pushNode(10); ml.pushNode(20); ml.display(); return 0; }
关键修复点说明
- 动态分配节点:用
new在堆上创建节点,内存不会随函数结束销毁,彻底解决悬垂指针问题。 - 修正指针赋值:直接给
Head和Current分配有效堆内存地址,避免逗号运算符的误用。 - 调整遍历逻辑:先跳过哨兵头节点,再遍历有效节点,避免空指针访问和内容遗漏。
- 添加析构函数:主动释放堆内存,避免C++中常见的内存泄漏问题(这和C#的GC机制差异很大)。
- 替换NULL为nullptr:C++11引入的类型安全空指针,比传统NULL更可靠。
内容的提问来源于stack exchange,提问作者samdavis112
相关产品推荐
相关产品推荐

