和其他容器一样,在学会创建容器后我们就要认识其迭代器。list同我们学过的vector一样,也有begin()、end()正向迭代器,rbegin()、rend()反向迭代器,更有可读不可改的cbegin()、cend()、crbegin()、crend()这种常量迭代器(c这里表示const,意为不可修改)。他们在链表中的位置如下图所示:

image.png

list和之前学过的deque、vector、array一样都是双向迭代器,支持++和--操作,但不是随机迭代器,不支持+5、-2操作。在前一节《初识STL库中的list容器》,我们通过begin()实现了list容器遍历,现在我们使用rbegin()来实现容器遍历:

#include<bits/stdc++.h>
#include<list>
/*通过list反向迭代器遍历容器 */
using namespace std;
void test()
{
list<int> l;//直接创建
for(int i=0;i<5;++i)
{
l.push_front(i+1);//链表也能通过push_front()头增元素 
}
/*{5,4,3,2,1}*/
for(auto it = l.rbegin();it!=l.rend();++it)cout << *it << " ";//链表不能通过'[]'访问元素 
cout << '\n';
}
 
int main(){
    test();
    return 0;
}

编译后:

使用反向迭代器

成功编译。值得注意的是正向迭代器是左减右加,反向迭代器是左加右减,在使用迭代器时要注意方向不要错了。

前面我们谈到,在使用vector、deque时,当容器进行”扩展行为“后需要更新迭代器,这是因为地址发生了变化。而我们的list容器则无需更新,这是由于list的结构就是通过指针链接新地址,原来数据没有更改地址,所以无需更新迭代器。举个例子:

vector进行“扩展行为”或“收缩行为”都需要及时更新迭代器:

#include<bits/stdc++.h>
#include<list>
#include<vector>

/*vector进行“扩展行为”或“收缩行为”都需要及时更新迭代器 */

using namespace std;

void test()
{
	vector<int> v{1,2,3,4,5};
	vector<int>::iterator beg = v.begin();
	cout << "能够输出第一个元素为:"<< *beg<<'\n' ;
	cout << "容器扩展后未能及时更新迭代器\n" ;
	v.push_back(6);
	cout <<"输出第一个元素为: "<< *beg<<'\n';
}
 
int main(){
    test();

    return 0;

}

编译结果为:

image.png

可以看到由于没有及时更新迭代器导致第一个迭代器解引用的值是11475440,这完全与1不相同,所以在使用vector等容器进行“扩展行为”或“收缩行为”都需要及时更新迭代器!

相比于list,则无需考虑这个,让我们通过代码来验证:

#include<bits/stdc++.h>
#include<list>
#include<vector>
/*list进行“扩展行为”或“收缩行为”无需更新迭代器 */
using namespace std;
void test()
{
list<int> l{1,2,3,4,5};
list<int>::iterator beg = l.begin();
cout << "能够输出第一个元素为:"<< *beg<<'\n' ;
cout << "容器扩展后未能及时更新迭代器\n" ;
l.push_back(6);
cout <<"输出第一个元素为: "<< *beg<<'\n';
list<int>::iterator end = --l.end();
cout << "能够输出最后一个元素为:"<< *end<<'\n' ;
cout << "容器扩展后未能及时更新迭代器\n" ;
l.pop_front();
cout <<"输出最后一个元素为: "<< *end<<'\n';
}
 
int main(){
    test();
    return 0;
}

通过对比试验,我的深刻认识到list可以不用像vector那样动态更新迭代器。

总结:本节我们详细了解了list迭代器的使用方法:list迭代器非随机迭代器,不能通过+5、-8这样随机访问(原因在于非连续内存存储),同时由于list特殊结构(由指针链接,无需更换地址),使得list进行“扩展行为”或“收缩行为”无需更新迭代器!

点赞(0)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)