迭代器提供一种方法能够访问一个容器里面的数据,而又不用暴露该容器内部的表达式,设计思想是将数据容器和算法分开,然后利用迭代器这个粘合剂将他们撮合在一起。
迭代器的使用要注意失效问题。(erase返回被删除迭代器的下一个迭代器)
对于顺序容器的失效:
void test()
{
vector<string> v = { "aaaaaaaaaa", "bbbbbbbbbb", "ccccccccc", "dddddddd","eeeeeeeeeeeee" };
vector<string>::iterator it = v.begin();
for (; it != v.end();)
{
if (*it == "ccccccccc")
v.erase(it);
else
it++;
}
}
例如这样对于vector,因为将“ccccccccc”删除后因为会发生崩溃的现象,因为vector是是顺序容器,删除它后“dddddddd“及后面的元素会立马向前移动,因为“ccccccccc"已经是一块被释放的空间,现在它已经是一块未知空间现在对它空间指派值会发生错误,因为没进行申请内存的动作。现在的做法让应该不使用这一块已经释放了得空间,所以对代码进行修改如下:
void test()
{
vector<string> v = { "aaaaaaaaaa", "bbbbbbbbbb", "ccccccccc", "dddddddd","eeeeeeeeeeeee" };
vector<string>::iterator it = v.begin();
for (; it != v.end();)
{
if (*it == "ccccccccc")
it=v.erase(it);
else
it++;
}
}
对于非顺序容器的的失效:
void test()
{
list<int> l;
l.push_back(1);
l.push_back(3);
l.push_back(5);
l.push_back(7);
list<int>::iterator it = l.begin();
for (; it != l.end();)
{
if (*it = 4)
{
l.erase(it);
}
else
it++;
}
}
因为list是一个双向链表,因为删除当前迭代器会使其找不到后面的节点,这样指针++后指向的是一块未知的空间,所以也会造成程序的崩溃。修改方式也是将erase的返回迭代器进行记录,直接就避免了对删除了那个节点进行++操作,这样就避免了崩溃。
修改后为:
void test()
{
list<int> l;
l.push_back(1);
l.push_back(3);
l.push_back(5);
l.push_back(7);
list<int>::iterator it = l.begin();
for (; it != l.end();)
{
if (*it = 4)
{
it=l.erase(it);
}
else
it++;
}
}