关于迭代器失效

今天技术群讨论了一个问题,关于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()前面的迭代器,还是尽量不要写成这种形式,依然采用文章中最开始的写法。

原文地址:https://www.cnblogs.com/scu-cjx/p/8581783.html