zoukankan      html  css  js  c++  java
  • c++迭代器失效问题

    参考两篇文章:https://blog.csdn.net/skyroben/article/details/70877008

    https://lichanghao.github.io/2016/08/01/C++%E4%B8%ADiterator%E5%A4%B1%E6%95%88%E7%9A%84%E9%97%AE%E9%A2%98/

    迭代器是一种面向对象的广义指针,用于指向容器中或流中的对象。可以看做是一种指向数据的指针。

    失效举例:

    删除vector容器中的偶数

    代码:

    #include  <iostream>
    #include  <vector>
    using namespace std;
    void Printvector(vector<int> &l)
    {
        vector<int>::iterator it = l.begin();
        while (it != l.end())
        {
            if (*it % 2 == 0)
            {
                //l.erase(it);    //(1)   1  输出之后崩溃
                //it=l.erase(it); //(2)   1 3 5 输出之后崩溃
            }
            cout << *it << " ";
            ++it;
        }
        cout << endl;
    }
    void Testvector()
    {
        vector<int> l;
        l.push_back(1);
        l.push_back(2);
        l.push_back(3);
        l.push_back(4);
        l.push_back(5);
        l.push_back(6);
        Printvector(l);
    }
    int main()
    {
        Testvector();
        return 0;
    }

    (1)程序输出1之后就崩溃的原因:

    通过调试观察现象: 

    这里写图片描述

    作者解释:明显可以看到使用erase删除某一个结点之后,vector迭代器虽然还是指向当前位置,而且也引起了元素前挪,但是由于删除结点的迭代器就已经失效,指向删除点后面的元素的迭代器也全部失效,所以不能对当前迭代器进行任何操作;需要对迭代器重新赋值或者接收erase它的返回值;

    个人理解:迭代器类似于一个指针,指向数据为2的节点时数据被删除,而且没有给迭代器重新赋值,那么此时此迭代器的指向不明确,输出该迭代器位置及后边位置的数据会造成程序崩溃。

    那么,如果给进行重新赋值

    作者解释:使用it接收erase的返回值,假如vector最后一个元素为奇数按照(2)的方式运行程序是不会崩溃的,这里崩溃的原因就好像数组访问越界,因为元素6已经被删除,不属于vector(数组)了,而你还继续对指向它的指针解引用,所以程序崩溃。

    个人理解:对it重新赋值后,遍历到6的位置时不会崩溃,但因为删除6节点后没有重新赋值,造成崩溃。

    STL中erase实现的源代码:

     iterator erase(iterator position) {
        if (position + 1 != end())
          copy(position + 1, finish, position);
        --finish;
        destroy(finish);
        return position;
      }

    (3)正确的使用方式

    void Printvector(vector<int> &l)
    {
        vector<int>::iterator it = l.begin();
        while (it != l.end())
        {
            if (*it % 2 == 0)
            {
                it = l.erase(it);
            }
            else
            {
                cout << *it << " ";
                ++it;
            }
        }
        cout << endl;
    }

    即只有在it指向明确的时候才进行输出,否则不输出

  • 相关阅读:
    实例告诉你如何把 if-else 重构成高质量代码!
    Java8 快速实现List转map 、分组、过滤等操作
    大学四年Java学习路线规划,所有私藏资料我都贡献出来了!
    Redis面试题汇总(附答案),面试突击专用
    代码优化大盘点:35 个 Java 代码优化魔鬼细节
    ES6+Webpack+Babel基本环境搭建
    抽象类和接口的异同及实例解析
    .NET ORM 哪家强
    Asp.Net 高性能ORM框架 SqlSugar.ORM 2.8
    ASP.NET 让无码编程不在是梦 -.NET通用平台、通用权限、易扩展、多语言、多平台架构框架
  • 原文地址:https://www.cnblogs.com/vactor/p/10593457.html
Copyright © 2011-2022 走看看