C++中的iterator(迭代器)失效

一、iterator的介绍

iterator(迭代器)就是c++中被用来访问一个容器类的所包函的全部元素,其行为像一个指针。

   string Str("hello");
     string::iterator ps;
     for (ps = Str.begin(); ps != Str.end(); ps++)   //begin()函数返回值为Str串的首地址。
     {
        cout << *ps;
     }

在这里插入图片描述

vector<int>v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
vector<int>::iterator pv;
for (pv = v.begin(); pv != v.end(); pv++)   //begin()函数返回值为容器v的首地址
{
	cout << *pv<<" ";
}

在这里插入图片描述

二、失效问题及解决方案

1.insert时失效

下面以vector容器为例:

   vector<int>v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    
    vector<int>::iterator iv = v.end();
    v.insert(iv, 10, 8);     //在iv处插入10个8。
    cout << *iv << endl;//iv插入数据后,realloc重新分配了空间,

在这里插入图片描述

程序此时抛出了一个内存异常,这种问题最好解决,下面我来画图来解释一下原因。

1.在未插入之前,v push_back了5个数据,iv指向容器尾地址

在这里插入图片描述

2.在插入之前看一下原来的容量:capacity = 6,此时要插入10个数据肯定得扩容,

注意:vs环境下vector是以1.5倍的扩容方式来扩的(Linux以2倍的方式扩容)。插入10个后capacity = (6*1.5<16) *1.5 = 19

在这里插入图片描述
扩容函数是通过realloc来开辟空间的,原来空间不够,它重新开一个新的空间,然后把原来的数据拷贝进去。
在这里插入图片描述由此可以看出,重新分配空间后,iv还是指向原来的被释放的空间,因此会抛出上面的内存异常。

3.解决方法

iterator insert(iterator &it,size_t n,T num) //insert返回了新插入第一个数据的位置。

v.insert(iv, 10, 8);
iv = v.insert(iv, 10, 8);  //用iv来接返回新空间中原来位置的值。

在这里插入图片描述

2.erase时失效

vector<int>v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
vector<int>::iterator iv = v.end();
v.erase(iv-1);//end()-1是最后一个位置的值
cout << *iv << endl;

和insert一样输出iv的值的时候抛出异常
在这里插入图片描述 下面一段代码是erase的源码

iterator erase(iterator __position) {
    if (__position + 1 != end())
      copy(__position + 1, _M_finish, __position);
    --_M_finish;
    destroy(_M_finish);//被erase的元素最后被destory掉,自然不能再访问。
    return __position;

解决方法和insert一样,用自己来接erase函数的返回值,就不会产生失效的问题。

iv = v.erase(iv-1);
cout << *iv << endl;
发布了77 篇原创文章 · 获赞 16 · 访问量 6537

猜你喜欢

转载自blog.csdn.net/weixin_43886592/article/details/101195529