面试中常被问到STL迭代器失效问题
Posted AllenSquirrel
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试中常被问到STL迭代器失效问题相关的知识,希望对你有一定的参考价值。
STL容器中迭代器失效的场景:
以vector为例进行分析
vector进行数据插入
- 如果空间充足那组,插入数据后,原有数据向后移动,导致迭代器失效
- 如果空间不足,插入新数据需要扩容,则发生拷贝,导致迭代器失效
void reverse(size_t n)
{
if (n > capacity())
{
//保存有效元素个数
size_t sz = size();
//申请空间
T* tmp = new T[n];
//拷贝原有空间
if (_start)
{
//memcpy(tmp, _start, sizeof(T)*size());//内置类型 进行深拷贝 如果自定义类型 进行浅拷贝
for (size_t i = 0; i < sz; i++)
{
tmp[i] = _start[i];//调用赋值运算符重载函数进行深拷贝,目的是 保证类型完成深拷贝(比如自定义string类型)
}
delete[]_start;
}
//更新
_start = tmp;
//_finish=_start+size();//由于start更新 导致size()出问题 finish丢失,需要提前记录size ,重新找到finish指向
_finish = _start + sz;
_endofstorage = _start + n;
}
}
void insert(iterator pos, const T& val)
{
//检查位置
assert( pos<=end()&&pos>=begin());
//检查容量
if (_finish == _endofstorage)
{
//记录偏移量
size_t offset = pos - _start;
size_t newcap = _endofstorage == nullptr ? 1 : 2 * capacity();
reverse(newcap);//增容空间拷贝导致迭代器失效 pos位置丢失
pos = _start + offset;//增容之后 更新pos位置
}
//移动元素
iterator it = end();
while (it>pos)
{
*it = *(it - 1);
it--;
}
*pos = val;
//更新
_finish++;
}
解决插入后迭代器失效的方法就是如果需要扩容就在插入前记录当前插入位置距起始位置的偏移量,扩容之后,根据偏移量更新插入位置,同时移动元素从后往前遍历,移动更新迭代器指向位置
vector进行数据删除
给一个int类型的vector容器增加20个整数,然后删除里面所有的偶数
vector<int> vec;
for(int i=0; i<20; ++i)
{
vec.push_back(rand()%100);
}
vector<int>::iterator it = vec.begin();
while(it!=vec.end())
{
if(*it % 2 == 0)
{
vec.erase(it);
}
else
{
++it;
}
}
上述代码中,删除第一个偶数后,起始位置到当前删除位置的迭代器都是正常的,之后的失效
解决方法如下:
vector<int> vec;
for (int i = 0; i < 20; ++i)
{
vec.push_back(rand() % 100);
}
vector<int>::iterator it = vec.begin();
while (it != vec.end())
{
if (*it % 2 == 0)
{
it = vec.erase(it);
}
else
{
++it;
}
}
return 0;
由于erase返回删除位置的下一位置,每次删除重新对迭代器赋值,更新迭代器位置指向,此时已经指向下一位置,所以不需要迭代器后移,否则会跳过部分数据,这个点经常出现在一些选择题代码分析上哦
以上是关于面试中常被问到STL迭代器失效问题的主要内容,如果未能解决你的问题,请参考以下文章