我创建了一些类似链的结构,其中一个对象具有指向链的下一个和上一个对象的指针。下面的代码遍历整个链,查找在参数中指定的值,并删除匹配的元素(如果存在)。
void List::removeElementByValue(int value)
{
ListMember* nextElem = this->firstValue;
while (nextElem) {
if (nextElem == NULL || nextElem == nullptr) {
break;
}
if (nextElem->value == value) {
if (nextElem->prevValue)
(nextElem->prevValue)->nextValue = nextElem->nextValue;
if (nextElem->nextValue)
(nextElem->nextValue)->prevValue = nextElem->prevValue;
delete nextElem;
this->count--;
return;
}
nextElem = nextElem->prevValue;
}
}
问题是:当我试图从链中删除不存在的值时出现此错误。
抛出异常:读取访问冲突。 nextElem是0xCDCDCDCD。
在这种情况下,函数应该什么也不做。它发生在这一行:
if (nextElem->value == value) {
如您所见,我已经使用多种方法来检查nextElem是否正确,但是仍然出现此错误。有什么方法可以防止这种情况发生?
答案 0 :(得分:1)
if (nextElem == NULL || nextElem == nullptr)
当while (nextElem)
为true时,它将始终为false。
nextElem = nextElem->prevValue;
这需要使用nextValue
而不是prevValue
。
但是,最重要的是,如果在列表的第一个元素中找到了this->firstValue
,则不会更新value
,因此最终您将删除firstValue
并使其指向无效的内存。
尝试以下方法:
void List::removeElementByValue(int value)
{
ListMember* elem = this->firstValue;
while (elem) {
if (elem->value == value) {
if (elem->prevValue)
elem->prevValue->nextValue = elem->nextValue;
if (elem->nextValue)
elem->nextValue->prevValue = elem->prevValue;
// ADD THIS!!!
if (elem == this->firstValue)
this->firstValue = elem->nextValue;
delete elem;
this->count--;
return;
}
elem = elem->nextValue; // NOT prevValue!
}
}
更好的解决方案是首先不要手动实现链接列表。请改用标准std::list
容器,让它为您完成所有艰苦的工作。
#include <list>
class List
{
private:
std::list<int> values;
...
};
...
#include <algorithm>
void List::removeElementByValue(int value)
{
auto iter = std::find(values.begin(), values.end(), value);
if (iter != values.end())
values.erase(iter);
}