EXC 对迭代器的错误访问

EXC Bad Access with Iterators

我创建了这个适用于向量、链表和双链表的函数。该函数获取一个值并在容器中搜索它。如果 vlaue 在容器中,则该函数会将值插入到已存在的位置旁边。因此,如果 val=2 那么 {3,2,5} 将变为 {3,2,2,5}。但是如果容器中不存在该值,则将其添加到后面。

我使用迭代器编写了这个函数。它与向量一起工作得很好,但是当我尝试 运行 它与列表或双链表时,我在 if (*it==val) 行收到 Exc Bad Access 错误。我没有看到我做错了什么。

template <class Container, class T>
void insertNextTo( Container &x, const T &val){
    typename Container::iterator it = x.begin();
    while (it!=x.end() && *it!=val){
        ++it;
    }
    if (*it == val){
        x.insert(it, val);
    }
    else{
        x.push_back(val);
    }
}

编辑:谢谢大家!您更改 if 语句的建议非常有效!

如果我错了有人纠正我,但我相信你的错误来自于这样一个事实,即当你的迭代器到达列表的末尾时,它实际上指向内存中列表最后一位之后的地址,它可能会或可能不会被初始化并且在范围内,这会导致您的程序出错。

如果该值尚不存在,当循环结束时it 将等于end(),并且您不能解引用end()。您需要将 if (*it == val) 改为 if (it != x.end())

//if (*it == val){
if (it != x.end()){
    x.insert(it, val);
}

或者,因为你只插入一个值,如果你找到 val 那么你可以执行 insert() 并立即退出函数,然后 push_back() 只有当循环到达容器的末端:

template <class Container, class T>
void insertNextTo( Container &x, const T &val ) {
    typename Container::iterator it = x.begin();
    while (it != x.end()) {
        if (*it == val) {
            x.insert(it, val);
            return;
        }
        ++it;
    }
    x.push_back(val);
}

在这种情况下,您可以使用 std::find() 而不是手动循环来简化代码:

#include <algorithm>

template <class Container, class T>
void insertNextTo( Container &x, const T &val ) {
    typename Container::iterator it = std::find(x.begin(), x.end(), val);
    if (it != x.end()) {
        x.insert(it, val);
    } else {
        x.push_back(val);
    }
}

甚至这样,因为使用 end() 迭代器 insert() 是安全的,它实际上与 push_back():

相同
template <class Container, class T>
void insertNextTo( Container &x, const T &val ) {
    typename Container::iterator it = std::find(x.begin(), x.end(), val);
    x.insert(it, val);
}

改变

if (*it == val)

至:

if (it != x.end())

如果在容器中找不到 val,则循环将在 it == x.end() 时结束。它指向数组末尾,因此间接通过它会导致未定义的行为。