EXC与迭代器的访问不良

时间:2016-03-31 00:47:39

标签: c++ linked-list iterator exc-bad-access

我创建了这个与矢量,链表和双链表一起使用的函数。该函数接受一个值并在容器中搜索它。如果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声明的建议完美无缺!

3 个答案:

答案 0 :(得分:2)

如果该值尚不存在,则在循环结束时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);
    }
}

或者甚至是这样,因为insert()使用end()迭代器是安全的,它实际上与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);
}

答案 1 :(得分:2)

更改

if (*it == val)

为:

if (it != x.end())

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

答案 2 :(得分:0)

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