【问题标题】:EXC Bad Access with Iterators带有迭代器的 EXC 错误访问
【发布时间】:2016-07-19 06:03:29
【问题描述】:

我创建了这个函数,它适用于向量、链表和双链表。该函数接受一个值并在容器中搜索它。如果 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 语句的建议非常有效!

【问题讨论】:

  • 如果未找到val,则if 条件将引用导致​​UB 的结束元素。

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


【解决方案1】:

改变

if (*it == val)

到:

if (it != x.end())

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

【讨论】:

    【解决方案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);
        }
    }
    

    甚至这样,因为使用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);
    }
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多