网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
C++剖析stl迭代器
迭代器
Iterator(迭代器)模式又称游标(Cursor)模式,用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。 或者这样说可能更容易理解:Iterator模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序(由iterator提供的方法)访问聚合对象中的各个元素。
由于Iterator模式的以上特性:与聚合对象耦合,在一定程度上限制了它的广泛运用,一般仅用于底层聚合支持类,如STL的list、vector、stack等容器类及ostream_iterator等扩展Iterator。
是什么?:
定义:
🥦 迭代器是指向元素范围(如数组或容器)中的某个元素的任何对象,它能够使用一组运算符(至少具有自增(++) 和解引用 (*) 运算符)循环访问该范围的元素。
🍊 迭代器最明显的形式是指针:指针可以指向数组中的元素,并且可以使用增量运算符 (++) 循环访问这些元素。但其他类型的迭代器也是可能的。例如,每个容器类型(如list )都有一个特定的迭代器类型,旨在循环访问其元素。
迭代器根据其实现的功能分为五类
STL常用容器迭代器类型
vector
的迭代器为 随机访问迭代器
list
的迭代器是 双向迭代器
slist
的迭代器是 前进迭代器
deque
的迭代器是 随机访问迭代器
set, map
的迭代器是 双向迭代器
迭代器的作用:
🥦 用于指向顺序容器和关联容器中的元素
🍊 通过迭代器可以读取它指向的元素
🍉 通过非const迭代器还可以修改其指向的元素
其实简单地讲就是可以让程序员🙉可以在使用元素过程中不用知道底层数据结构的实现,使访问更加的简单,方便。
demo:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v{ 1, 2, 3, 4, 5, 6, 7 }; //C++ 11语法
vector<int>::iterator my_it = v.begin;
//auto my\_it = v.begin();
// 迭代器遍历输出
while (my_it != v.end()){
cout << \*my_it << endl;
++my_it;
}
return 0;
}
stl源码中
vector
迭代器的定义
迭代器 和 指针
🥦 迭代器所表现出的功能很像指针,但并不能和指针划等号; 迭代器并不是指针,而是类模板,表现的像指针。
他只是模拟了指针的一些功能,重载了指针的一些操作符,–>、++、–等。迭代器封装了指针,是一个"可遍历STL( Standard Template Library)容器内全部或部分元素"的对象,本质是封装了原生指针 (T*),是指针概念的一种提升,提供了比指针更高级的行为,相当于一种智能指针,他可以根据不同类型的数据结构来实现不同的++,–等操作。
🍊迭代器返回的是对象引用而不是对象的值,所以cout只能输出迭代器使用取值后的值而不能直接输出其自身。
指针是迭代器的一种形式,迭代器和指针有类似的元素操作功能
相同点:
🍒 都可以进行整数操作的加减运算; 都可以同类型相减得到元素个数
区别:
迭代器:
🥑 迭代器不是指针是类模版,表现像指针。迭代器是指针的抽象和泛化,它模拟了一些指针的功能, 通过重载指针的一些操作符。本质是封装了原生指针,相当于指针的一种升级。
🥑 迭代器返回的是对象引用而不是对象的值
🥑 指针能指向函数;而迭代器只能指向容器。
🥑 指针只能用于某些特定的容器;迭代器是指针的抽象和泛化。
迭代器失效
🥦 其实迭代器底层对应指针所指向的空间被销毁了,而使用非法的空间造成错误, 可能会导致程序崩溃的后果。
vs2013 中的迭代器失效
迭代器失效情况
用容器迭代器erase
失效情形如下。
🥦 对于序列容器vector
,deque
来说,使用erase
后,后边的每个元素的迭代器都会失效,后边每个元素都往前移动一位,erase
返回下一个有效的迭代器。
deque迭代器失效
其中插入头尾操作引用不失效的原因是,deque由一个map和连续数组组成,其中map是指向数组的指针即二级指针,当插入头尾时,如果内存不够,会①复制原map的信息②申请新的连续空间作为map③存入旧的map信息,然后再插入新的数据。而deque的迭代器中存放着cur(当前数组的位置)first和end(当前map节点的首位地址)和node(当前map的节点地址),所以由于map的从新分配,迭代器的node失效,但是原map指向的连续数组并没有从新分配。
🍊 对于关联容器map
,set
来说,使用了erase
后,当前元素的迭代器失效,但是其结构是红黑树,删除当前元素,不会影响下一个元素的迭代器,所以在调用erase
之前,记录下一个元素的迭代器即可。(解决方式)
list迭代器失效
🍉 list迭代器失效即迭代器所指向的那个结点失效了,即该结点被删除了。对于list
来说,底层结构为带头双向循环链表,它使用了不连续分配的内存。插入并不会导致迭代器的失效,不会扩容开辟新空间。只有在删除的时候才会失效,并且失效的只是指向被删除结点的迭代器,其它的迭代器并不会收到影响。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!