不使用Iterator也可以遍历,为什么非要使用Iterator?
现在我们常用的容器vector,list,map,set,multiset,map,multimp,deque 这几个容器的内部是实现有顺序表,链表,红黑树. 那我们遍历这些容器就要明白它的底层构造,这样很不方便. Iterator就是在底层给你定义好,然后任何容器都是同样的遍历方式.这样就算你不懂底层实现也可以使用.所以就是可以操作容器,又不需暴露该对象的内部表示。或者这样说可能更容易理解:Iterator模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序(由iterator提供的方法)访问聚合对象中的各个元素。
Iterator++的内部实现
_Myiter operator++(int)
{
_Myiter _Tmp=*this;
++*this;
return (_Tmp);
}
Iterator的使用
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int> a(5, 3);
vector<int>::iterator it = a.begin();
while (it!=a.end())
{
cout << *it << " ";
it++;
}
}
运行结果为:3 3 3 3 3
const_iterator
该类型只能访问容器内元素,但不能改变其值。当我们对普通iterator类型解引用时,得到对某个元素的非const引用。而如果我们对const_iterator类型解引用时,可以得到一个指向const对象的引用,如同任何常量一样,该对象不能进行重写。
Iterator失效场景
迭代器失效,就是你删除该节点后节点的迭代器因为变成一个随机值,没有办法跳转到下一个节点. 这个时候你的迭代器++之后就是一个随机值,最后程序再次使用到it时,程序崩溃. 这就类似于野指针的问题.
对于失效场景的改进
#include<bits/stdc++.h>
using namespace std;
int main(void)
{
vector<int> vi;
vector<int>::iterator it;
for (int i = 1; i <= 10; i++)vi.push_back(i);
for (it = vi.begin(); it != vi.end(); it++)
{
if (*it == 3)it = vi.erase(it);//删除3
cout << *it;//1 2 4 5 6 7 8 9 10
}
}
#include<bits/stdc++.h>
using namespace std;
int main(void)
{
map<int, string> mis;
map<int, string>::iterator it;
for (int i = 1; i <= 10; i++)mis.insert(make_pair(i, "s"));
for (it = mis.begin(); it != mis.end(); it++)
{
if (it->first == 3)it = mis.erase(it);
cout << it->first << ":" << it->second << endl;
}
}
#include<bits/stdc++.h>
using namespace std;
int main(void)
{
list<int> li;
list<int>::iterator it;
for (int i = 1; i <= 10; i++)li.push_back(i);
for (it = li.begin(); it != li.end(); it++)
{
if (*it == 3)it = li.erase(it);
cout << *it;
}
}
这里erase删除元素之后给迭代器赋予了下一个迭代器。
因为序列式容器的内存是连续分配的,删除其中一个会导致后面所有的元素前移一个位置以保证数据的紧凑。