C++链表删除单节点时误删整个列表且析构报访问越界问题
问题根因分析
你的代码存在两个核心错误,直接导致了访问违例和链表结构损坏:
- 指针操作逻辑完全错误
处理头节点时你写了*scans = currentScan->getNext();,这里scans是Scan*类型的头指针,你需要修改的是指针本身的指向,而不是指针指向的对象内容。你当前的写法是把第一个节点的属性覆盖为第二个节点的属性,并没有修改scans的指向,delete currentScan后scans直接指向已释放的内存,变成野指针,析构遍历链表时必然触发访问违例。
循环中*previousScan = currentScan也是同样的错误,你是要移动previousScan指针到currentScan的位置,不是把previousScan指向的对象赋值为currentScan指向的对象,这会直接破坏链表节点的原有属性。 - Scan类的赋值运算符重载不符合规范
C++标准拷贝赋值运算符的签名应为Scan& operator=(const Scan& scan);,你实现的是接收指针参数的重载,完全不符合常规拷贝赋值场景,且你错误的解引用赋值操作会调用这个错误的重载,直接浅拷贝next指针,进一步加剧链表结构的混乱。
修正后的代码
修正removeScan函数
bool ScanList::removeScan(int serialNumber) {// post: IF serialNumber is present in the list // THEN scan has been removed from it and true has been returned // ELSE false has been returned Scan* currentScan = scans; Scan* previousScan = nullptr; if (currentScan != NULL && currentScan->getSerialNumber() == serialNumber) { // 修改头指针本身的指向,不要解引用 scans = currentScan->getNext(); delete currentScan; return true; } while (currentScan != NULL && currentScan->getSerialNumber() != serialNumber) { // 移动previousScan指针,不要解引用 previousScan = currentScan; currentScan = currentScan->getNext(); } if (currentScan == NULL) { return false; } previousScan->setNext(currentScan->getNext()); delete currentScan; return true; }
修正Scan类拷贝赋值运算符
Scan& Scan::operator=(const Scan& scan) { if (this == &scan) { return *this; } this->serialNumber = scan.serialNumber; this->timesRecycled = scan.timesRecycled; // 单个节点赋值不要直接拷贝next指针,避免破坏链表结构,有深拷贝需求时单独处理节点链表 this->next = nullptr; return *this; }
内容的提问来源于stack exchange,提问作者Esmee
相关产品推荐
相关产品推荐

