一、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;