迭代器失效:
如果迭代器失效,那么就不能再使用这个迭代器。
如果使用,那么结果是未定义的。
我们以模拟实现vector的insert为例。
一、野指针
1、insert实现
这里的pos会变成野指针。
当扩完容后,由于空间的改变,_start和_finish和_endofstorage的指向就变了。所以pos失效。
void insert(iterator pos, const T& x)
{
if (_finish == _endofstorage)
{
reserve(capacity() == 0 ? 4 : capacity() * 2);
}
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
--end;
}
*pos = x;
++_finish;
}
2、Test
void Test()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.insert(v.begin(), 0);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
v.insert(v.end(), 0);
v.insert(v.end(), 0);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
3、解决方案
(1)代码
我们可以在扩容之前,先记录pos的偏移量,然后在扩容后,pos更新,这样就解决了上述问题。
void insert(iterator pos, const T& x)
{
size_t len = pos - _start; //记录位置
if (_finish == _endofstorage)
{
reserve(capacity() == 0 ? 4 : capacity() * 2);
}
pos = _start + len; //更新位置
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
--end;
}
*pos = x;
++_finish;
}
(2)Test
二、迭代器传值
1、示例
insert插入后it 就失效了(扩容后就会失效),无法访问
因为扩容后,it还是指向旧空间,无法对新空间进行操作。
void insert(iterator pos, const T& x)
{
size_t len = pos - _start;
if (_finish == _endofstorage)
{
reserve(capacity() == 0 ? 4 : capacity() * 2);
}
pos = _start + len;
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
--end;
}
*pos = x;
++_finish;
}
void Test()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
v.insert(v.end(), 0);
v.insert(v.end(), 0);
vector<int>::iterator it = v.begin() + 3;
v.insert(it, 88);
v.insert(it, 88);
v.insert(it, 88);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
2、解决方案
在STL库的实现中,会告知insert之后迭代器会失效,不要进行使用。
所以我们应尽量避免使用,或多次使用时,在使用前更新迭代器。