最简可用单向链表需node存数据和next指针、linkedlist管head及操作;必须初始化next为nullptr、head为nullptr,所有修改操作前判空,遍历时根据需求选while(curr)或while(curr->next),并实现迭代析构防泄漏。

怎么手写一个能用的 Node 和 LinkedList 类
单向链表不是靠“背结构”写出来的,是靠明确每个节点要存什么、谁连谁、边界在哪。最简可用版本只需要两个类:Node 存数据和 next 指针,LinkedList 管头指针和基本操作。
常见错误是把 Node 设成 public 成员全暴露,或者在 LinkedList 里漏掉空指针检查,一插入/删除就崩。
-
Node的next必须初始化为nullptr,别依赖默认值 -
LinkedList的构造函数必须显式设head = nullptr - 所有修改
head或next的操作(如push_front、pop_front)都要先判空
示例(极简插入):
void push_front(int val) {
Node* new_node = new Node{val, head}; // 注意:new_node->next = head
head = new_node;
}为什么 pop_front 容易段错误
因为没处理 head == nullptr 就直接解引用 head->next,或者删完没置 head = nullptr,导致后续操作访问野指针。
立即学习“C++免费学习笔记(深入)”;
真实场景中,这个函数常被用在循环清理、队列出队、或作为其他操作(如反转)的前置步骤,一旦崩,堆栈里看不到明显线索,只报 Segmentation fault (core dumped)。
- 必须在开头加
if (!head) return; - 删节点前先缓存
head->next,再delete head,最后赋新head - 别写
delete head; head = head->next;—— 这句的head->next是已释放内存
迭代遍历时 while (curr) 和 while (curr->next) 差在哪
前者遍历全部节点(含最后一个),后者停在倒数第二个——这直接影响你能不能安全访问 curr->next->data,也决定是否漏掉尾节点处理。
比如实现 find_last() 或 “删除值为 x 的节点”,用错条件会导致找不到、删错位置、甚至越界读。
- 想访问当前节点内容(如打印、比较)→ 用
while (curr) - 想修改
curr->next(如插入到 curr 后、删除 curr 后节点)→ 用while (curr->next) - 永远不要在
while (curr->next)循环体内写curr = curr->next->next,容易跳过节点
不写析构函数会怎样
程序退出时看似没事,但只要链表生命周期在局部作用域外(比如成员变量、动态分配对象),就会内存泄漏——而且 valgrind 会明确报 definitely lost,每漏一个 Node 就丢 16 字节(x64 下 int + pointer)。
更隐蔽的问题是:如果 Node 里存的是资源句柄(如 FILE*、自定义对象),不手动清理会导致文件未关闭、析构逻辑跳过。
- 析构必须递归或迭代释放所有节点,不能只删
head - 推荐迭代写法,避免深递归爆栈(长链表 > 10k 节点时明显)
- 删节点后立刻设指针为
nullptr,防止二次释放(尤其调试时反复跑)
真正难的不是写对一次,是在增删混杂、异常路径(比如中间 new 失败)、多线程没加锁的情况下,还能保持指针关系不乱。这时候,head 是不是始终指向有效节点,next 是否总为 nullptr 或合法地址,比代码多不多行重要得多。










