本博客将记录:迭代器iterator这个知识点的笔记!在我们之前的学习过程中一般都把迭代器理解为一种特殊形式的指针,因为迭代器也有解引用的操作 *it ...,奔着想成为一名优秀的cpp开发人员的目的,那么今天我就来详细地学习了解下迭代器这个知识点。今天主要是学习迭代器的演绎、失效分析以及弥补、实战的内容。
这方面知识分为以下7个点:
一、迭代器简介
二、容器的迭代器类型
三、迭代器begin()/end()的操作,以及反向迭代器rbegin()/rend()的操作
四、迭代器运算符
五、const_iterator 迭代器
(5.1)cbegin()和cend()的操作
六、迭代器失效
(6.1)灾难程序演示1
(6.2)灾难程序演示2
七、范例演示
(7.1)用迭代器遍历sring类型数据
(7.2)vector容器的常用操作与内存释放
一、迭代器简介
迭代器:是一种用来遍历容器内元素的 数据类型,这种数据类型从直观上看有点类似于指针,我们大可以把它理解为,迭代器就是用来指向容器中的某个元素的。
通过使用迭代器,我们既可以读容器中的元素值,也可以修改某个迭代器所指向的元素的值
前面我们回顾了string和vector这2种容器,都可像使用一维数组那样去读取or修改其元素,也即用[]符号来do。
string str = "lzf"; cout << str[0] << endl;//str[0] == 'l';//读取 str[0] = 't';//str[0] == 't';//修改 cout << str[0] << endl; vectorvec{ 1,3,5,7 }; cout << vec[0] << endl;//vec[0] == 1;//读取 vec[0] = 1001;//vec[0] == 1001;//修改 cout << vec[0] << endl;
但是,后面我们还会继续回顾更多的容器类型(比如list/map),这些容器类型有些支持[]符号去读写相应的元素值,有些则不支持。因此,我们就可以使用迭代器了,因为对于每一种容器而言,都具有其本身自带的迭代器。访问容器的最常用的方式就是用迭代器来do!
string str = "lzf"; string::iterator itStr = str.begin();//string类型的开始迭代器 cout << *itStr << endl;//<===> str[0] == 'l';//读取 *itStr = 't';//<===> str[0] == 't';//修改 cout << *itStr << endl; vectorvec{ 1,3,5,7 }; vector ::iterator itVec = vec.begin();//vector 类型的开始迭代器 cout << *itVec << endl;//<===> vec[0] == 1;//读取 *itVec = 1001;//<===> vec[0] == 1001;//修改 cout << *itVec << endl;
二、容器的迭代器类型
定义容器迭代器的一般格式:
迭代器对应的容器的类型::iterator 普通迭代器变量名;//普通迭代器可读可写 用法举例:vector::iterator it = v.begin() | it = v.end(); 迭代器对应的容器的类型::reverse_iterator 反向迭代器变量名;//反向迭代器可读可写 用法举例:vector ::reverse_iterator it = v.rbegin() | it = v.rend(); 迭代器对应的容器的类型::const_iterator 常量迭代器变量名;//常量迭代器只读不可写 用法举例:vector ::const_iterator it = v.begin() | it = v.end();
//下面还是以vector这种容器来演示迭代器的类型 vectorvec {10,20,30,}; vector ::iterator it;//it就是个迭代器,是对应vector 这种容器的迭代器
我们在理解的时候,可以直接把vector
三、迭代器begin()/end()的操作,以及反向迭代器rbegin()/rend()的操作:
每个容器中都会内置好了正向开头迭代器begin()和正向末尾迭代器end(),反向开头迭代器rbegin()和反向末尾迭代器rend()这4种函数。这些函数让我们可以访问容器中的all元素。
正向迭代器:begin()和end()这2个函数的返回值就是对应位置处的迭代器。
(当需要在容器中从前往后遍历访问元素值时,就使用这种普通的正向迭代器)
反向迭代器:rbegin()和rend()这2个函数的返回值也是对应位置处的迭代器。
(当需要在容器中从后往前遍历访问元素值时,就使用这种反向(或说逆向)迭代器)
vectoriv = { 100,200,300,400,500 }; vector ::iterator it = iv.begin();//定义了一个迭代器(变量),类型是 vector while (it != iv.end()) { cout << *it << "t"; //一开始it指向iv[0]这个位置的迭代器,解引用*it就是取其值的意思 //然后不断遍历下去知道走到了iv的last一个位置的下一个位置处 //这好比你遍历访问一个数组int a[4]{1,2,3,4,};for循环中的最后一个i肯定是遍历到4了才推出循环的 it++;//指向下一个位置处的迭代器 } cout << "n-------------------------------" << endl; //reverse_iterator是反向迭代器 vector ::reverse_iterator rit = iv.rbegin(); while (rit != iv.rend()) { cout << *rit << "t"; rit++;//指向下一个位置处的迭代器 }
运行结果:
可能有些小伙伴没有搞懂begin()和rbegin()有啥区别,end()和rend()有啥区别,那么现在我就画张图帮大家搞clear:
补充一下用for_each()标准遍历算法配合rbegin(),rend()的使用代码:
vectoriv = { 100,200,300,400,500 }; void print(const int& val) { cout << val << "t";} //用正向迭代器输出vector容器对象所存储的all元素 for_each(iv.begin(), iv.end(), print);//100,200,300,400,500 cout << "n-------------------------------" << endl; //用反向迭代器输出vector容器对象所存储的all元素 for_each(iv.rbegin(), iv.rend(), print);//500,400,300,200,100 cout << endl;
运行结果同上!
此外,迭代器的操作中还有2个需要格外注意的事项:
注意事项1:当一个容器为空时(也即一个元素都没有时)有:begin()==end(), rbegin()==rend()
vectoriv;//空的vector容器 if (iv.begin() == iv.end())cout << "iv.begin() == iv.end()" << endl; if (iv.rbegin() == iv.rend())cout << "iv.rbegin() == iv.rend()" << endl;
运行结果:
注意事项2:用迭代器遍历容器时,有2种方法
vectoriv = { 100,200,300,400,500 }; void print(const int& val) { cout << val << "t";} 方法一、用标准算法库中所提供的for_each()来do遍历操作(推荐使用) //正向遍历输出 for_each(iv.begin(), iv.end(), print);//100,200,300,400,500 cout << "n-------------------------------" << endl; //反向遍历输出 for_each(iv.rbegin(), iv.rend(), print);//500,400,300,200,100 cout << endl; 方法二、用for循环来do遍历操作 //正向遍历输出 for(vector ::const_iterator it = iv.begin();it!=iv.end();it++){ cout<<*it<<"t";100,200,300,400,500 } cout< ::reverse_iterator rit = iv.rbegin();rit!=iv.rend();rit++){ cout<<*rit<<"t";//500,400,300,200,100 } cout< (对于反向的迭代器来说,rit++意味着是从后往前去加加,如果你误以为这里要写为rit--的话,那么请你再仔细看一下我在上面所画的那一张图!看完之后相信你就能完全理解反向迭代器是如何遍历的了!)
四、迭代器运算符
未完待续。。。(明天凡凡继续加油干!!!)



