C++链表添加节点触发无限循环的原因及修复方案求助
问题原因及修复方案
核心问题:被移除节点的pNext未清空
调用Remove函数移除节点后,被移除节点的pNext指针仍保留着之前的链表指向,后续再次将这些节点添加到链表末尾时,会触发循环链表:
- 初始链表为
E->D->C->B->A - 移除
C时,仅修改了D的pNext指向B,但C的pNext依然指向B - 调用
AddToEnd(&C)时,C被加到链表尾部,此时C的pNext指向B,B的pNext指向A,A的pNext指向C,形成B->A->C->B的循环,最终导致Print函数无限循环。
另外,Print函数采用对象拷贝的方式遍历链表,会放大循环问题——一旦出现循环,拷贝操作会无限进行。
修复步骤
1. 修复Remove函数,清空被移除节点的pNext
移除节点后必须重置其pNext为NULL,同时增加边界判断避免空指针访问:
void Garage::Remove(Car *r) { Car *tmp = this->pHead; Car *prev = NULL; if (pHead == r) { pHead = r->pNext; r->pNext = NULL; // 清空被移除节点的指针 return; } while (tmp != NULL && tmp != r) { prev = tmp; tmp = tmp->pNext; } // 避免节点不存在时的空指针操作 if (tmp != NULL && prev != NULL) { prev->pNext = tmp->pNext; tmp->pNext = NULL; // 清空被移除节点的指针 } }
2. 修复Print函数,改用指针遍历
原函数通过拷贝Car对象遍历,效率低且易触发无限拷贝,改用指针遍历更安全高效:
void Garage::Print(const char *string) { Trace::out("Garage(%s): \n",string); Car *tmp = pHead; // 使用指针而非对象拷贝 while (tmp != NULL && tmp->pNext != NULL) { Trace::out("\tCar(%s)--->%s \n", tmp->pName, tmp->pNext->pName); tmp = tmp->pNext; } if (tmp != NULL) { Trace::out("\tCar(%s)--->%s \n", tmp->pName, "(null)"); } Trace::out("\n"); }
3. 简化AddToFront函数的冗余代码
原函数的分支判断是冗余的,可简化为通用逻辑:
void Garage::AddToFront(Car *r) { r->pNext = this->pHead; // 直接指向原头节点 this->pHead = r; // 更新头节点 }
无论原头节点是否为NULL,该逻辑都成立。
额外注意事项
- 确保所有
Car对象的pNext初始值为NULL(你的构造函数已实现,无需修改) - 字符串字面量作为
pName的指向,生命周期足够长,无需额外处理
内容的提问来源于stack exchange,提问作者Helpme
相关产品推荐
相关产品推荐

