zoukankan      html  css  js  c++  java
  • 关于迭代器失效

    今天技术群讨论了一个问题,关于stl迭代器失效的,主要是关于vector和map删除元素的,但后来引申出了一个新的问题,特此记录一下。

    (一)关于vector和map删除元素

    首先是关于vector和map利用迭代器删除元素的方法,代码:

        vector<int> test1 = {1,1,1,1,1,1,1};
        for (auto iter = test1.begin(); iter != test1.end(); )
        {
            if (*iter == 1)
                iter = test1.erase(iter);
            else
                ++iter;
        }

    首先vector的迭代器在删除元素后会使得该迭代器之后的所有迭代器都失效,所以单纯使用test1.erase(iter)下次再次for循环程序很有可能直接崩溃。而由于vector的erase会返回当前删除元素的下一个元素迭代器,所以将返回值重新赋值给iter,避免了迭代器失效的

    问题。

    在看下map元素的删除,代码:

    map<int, int> test;
    for (int i = 0; i < 10; ++i)
    {
        test[i] = 1;
    }
    
    for (auto iter = test.begin(); iter != test.end(); )
    {
        if (iter->second == 1)
        {
            iter = test.erase(iter);
        }
        else
            iter++;
    }

    其实和vector迭代器删除元素类似,也需要将删除后的迭代器返回。早期map的erase返回类型为void(返回删除元素的下一个迭代器是c++11引入的新特性?这句话不确定是否正确,但现在的确可以返回迭代器了),所以map删除元素的方式还可以采用

    test.erase(iter++)。

    (二)vector迭代器begin()之前是啥?

    直接贴测试代码吧:

    vector<int> test2 = {1,1,1,1,1,1,1};
    cout<<test2[-1]<<endl;
    vector<int>::iterator iter2 = test2.begin();
    --iter2;
    *iter2 = 5;
    int a = *iter2;
    cout<<a<<endl;

    结果:

    test[-1]指向一个没有初始化的内存区域,但上述操作并没有引起程序崩溃,而且将iter2指向begin()并--iter2后赋值程序也正常输出结果,故该块内存区域是有成功映射到物理页的(不然写一块没有映射的地址,程序就崩了)。

    所以,对于删除vector中的元素,之前看到过一种写法为:

    vector<int> test2 = {1,1,1,1,1,1,1};
    for (auto iter = test2.begin(); iter != test2.end(); ++iter)
    {
        if (*iter == 1)
        {
            iter = test2.erase(iter);
            --iter;
        }
    }

    在最终结果上并没有什么问题,但是第一次删除元素后--iter,iter指向了begin()前面的迭代器,还是尽量不要写成这种形式,依然采用文章中最开始的写法。

  • 相关阅读:
    网络基础
    Web开发几种常用工具
    win组合键概述(windows10)
    Alfred使用
    Java8之新特性--modules
    jsp九大内置对象和四大作用域
    authtype
    Myeclipse中的快捷键
    如何在Jenkins CI 里调试
    写好unit test的建议和例子
  • 原文地址:https://www.cnblogs.com/scu-cjx/p/8581783.html
Copyright © 2011-2022 走看看