C++ STL 迭代器失效

一、学习资料
STL迭代器的使用

二、vector容器获取值是下标法和at()的区别

vector<int> vA;
int array[]={0,1,2,3,4};
vA.assign(array,array+5);
cout<<vA[6]<<endl;
cout<<va.at(6)<<endl;

如上述代码,当使用vA[6]的方式出现访问越界时,依然能得到一个结果,而使用at(6)的方式时程序就会抛出一个数组越界的异常,所以为了及时发现程序错误,访问容器内容时推荐使用at()的方式。

三、迭代器的使用
STL中有vector/list/queue/stack等多种容器,每种容器都有特有的访问方式,这是不利于我们记忆和使用的。迭代器的出现就是为了提供一套统一的STL访问方式,提高编程的效率。
使用方法:
1.声明(以vector为例): vector::iterator it; 声明一个vector类型的迭代器
2.定义:
it=vA.begin(); 让迭代器指向vA的第一个元素位置
it=vA.end(); 让迭代器指向vA的最后一个元素位置的下一个位置
【易错点注意:end()是最后一个元素位置的下一个位置(如下图)】

C++ STL 迭代器失效_第1张图片
3. 获取当前迭代器对应位置的元素
迭代器可以理解为一个指针,要获取迭代器所指位置的元素,就可以像指针一样加一个解引用符*(迭代器重载了该运算符),那么想要通过迭代器输出容器中每一个元素就可以通过迭代器自增来遍历

vector<int> vA;
int array[]={0,1,2,3,4};
vA.assign(array,array+5);
vector<int>::iterator it;
for(it=vA.begin();it!=vA.end();it++){
    cout<<*it<<endl;
}
  1. 迭代器可以通过it=it+n来访问容器中的任意元素
it=vA.begin();
it=it+3;
cout<<*it<<endl;

四、插入和删除时迭代器失效
1.
intsert(it,p): 在当前迭代器it指向的位置插入一个元素,内部逻辑:当前位置和后面每一个元素都往后移一位,然后将要插入的值p写入当前位置。
erase(it): 删除迭代器it所指位置的元素,内部逻辑:当前位置后的每一个元素向前移动一个位置,于是当前位置元素被覆盖掉,就相当于删除了。
【注:无论是插入和删除,it指向的位置始终没变,只是相应位置的元素发生了变化】

当使用insert()函数进行容器元素插入或者使用erase()函数进行删除操作时可能导致迭代器失效!

vector<int> vA;
int array[]={0,10,22,33,40};
vA.assign(array,array+5);

vector<int>::iterator it=vA.begin()+4; //此时迭代器指向的是40这个元素的位置
vA.insert(it,8);
cout<<*it<<endl;

上面这段代码就是在下标为4的位置插入一个元素8,插入之后vA内部就应该是{0,10,22,33,8,40},迭代器的位置没有发生变化,那它指向的位置就是元素8所在的位置,以上逻辑看似没什么问题,但是在有些编译器里是编译不通过的,这是为什么呢?
考虑一下vector容器的内存管理方式,vector内元素是连续存储的,当增加一个元素,而当前位置已经没有空间容纳新的元素时,就会另外开辟一段新的空间将vector整个迁移过去,并且释放掉当前占用的空间。看上述代码,it指向的那块空间可能已经释放掉了,所以再执行cout就会报错。
那么怎么解决呢?
insert()它是有返回值的,并且它返回的就是新内存空间中元素8对应的迭代器地址,所以我们只需将上述vA.insert(it,8)修改成it=vA.insert(it,8),这就表示it指向了新的内存空间中正确的位置,这个问题就解决了。
erase()函数同理,一定要接收返回值。

你可能感兴趣的:(c++,开发语言)