当前位置: 首页 > news >正文

c++:迭代器(Iterator)

目录

🚪什么是迭代器?

🔧 迭代器的本质

为什么不用普通数组或下标?

STL容器的迭代器并不是共用一个类型!

迭代器的类型(Iterator Categories)

📦 常见容器的迭代器类型

✅ 迭代器最常用的动作

🚸 初学者推荐写法:使用 auto 和 范围for


🚪什么是迭代器?

迭代器 = “智能指针”,用来一个一个地访问容器中的元素

你可以想象迭代器像是容器中的“手指”或“光标”:

  • 指着某个元素

  • 可以向前走(甚至有些还能往后走)

  • 能取出或修改元素

 示例对比:用数组 vs 用迭代器

int arr[] = {10, 20, 30};
for (int i = 0; i < 3; i++) {std::cout << arr[i];
}

改成 vector + 迭代器写法: 

std::vector<int> v = {10, 20, 30};
for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {std::cout << *it;
}
  • v.begin():返回指向第一个元素的迭代器

  • v.end():返回“超出最后一个元素的下一个位置”的迭代器

  • *it:表示取出当前指向的元素

  • ++it:移动到下一个元素

🔧 迭代器的本质

迭代器是一个类类型(不是基本类型)

虽然它看起来像指针(用 *it 解引用,用 ++it 移动),但它本质上是一个 C++ 类对象,封装了访问容器内部元素的逻辑。

🚩你可以这样理解:

指针迭代器
访问数组元素访问容器元素
*ptr 获取值*it 获取元素
是内建类型是类类型(有重载了 *, ++, == 等操作符)

🎓 举个例子看看类型:

std::vector<int> v = {1, 2, 3};
auto it = v.begin();
  • it 实际的类型是 std::vector<int>::iterator

  • 你可以打印:

std::cout << typeid(it).name() << std::endl;

输出可能是:__gnu_cxx::__normal_iterator<int*, std::vector<int>>

🔍 它是一个内部实现的类,封装了指针行为,但比裸指针更安全、更通用。


为什么不用普通数组或下标?

STL 有很多不同的容器:链表、哈希表、红黑树……
它们里面的元素并不一定支持下标 [],但每种容器都提供了“迭代器”接口,你可以统一方式遍历。

容器支持下标?支持迭代器?
vector
list
set
map

每个容器都有自己专属的迭代器类型,std::vector<T>::iterator  这种写法是访问这个类型的一种方式。

STL容器的迭代器并不是共用一个类型!

容器类型对应迭代器类型
std::vector<T>std::vector<T>::iterator
std::list<T>std::list<T>::iterator
std::set<T>std::set<T>::iterator
std::map<K,V>std::map<K,V>::iterator
std::vector<int>::iterator it;  // vector 的迭代器
std::list<double>::iterator it2;  // list 的迭代器

为什么不统一一个 iterator 类型呢?
👉 因为不同容器的内部结构不同(如数组 vs 链表 vs 红黑树),它们的迭代器行为也不同。比如:

  • vector 支持随机访问 (it + 3)

  • list 只支持前后移动(++it, --it

 

迭代器的类型(Iterator Categories)

STL 根据迭代器的能力,把迭代器分成 五类,从弱到强如下:

类型功能示例容器
InputIterator单向只读istream_iterator
OutputIterator单向只写ostream_iterator
ForwardIterator单向读写forward_list
BidirectionalIterator可双向移动list, set, map
RandomAccessIterator支持随机访问 it+n, it1-it2vector, deque, array

💡 STL 算法会根据迭代器的种类选择最优的操作方式。

 

📦 常见容器的迭代器类型

容器支持的迭代器类型
vector, deque, array随机访问迭代器(RandomAccessIterator)
list双向迭代器(BidirectionalIterator)
forward_list单向迭代器(ForwardIterator)
set, map, multimap, multiset双向迭代器(BidirectionalIterator)
unordered_map, unordered_set同样为双向迭代器

随机访问迭代器(vector): 

std::vector<int> v = {1, 2, 3, 4};
auto it = v.begin();
std::cout << *(it + 2);  // 输出:3

 双向迭代器(list):

std::list<int> l = {1, 2, 3};
auto it = l.end(); --it;
std::cout << *it;  // 输出:3

 单向迭代器(forward_list):

std::forward_list<int> fl = {1, 2, 3};
auto it = fl.begin();
++it;  // 可以前进,但不能后退


✅ 迭代器最常用的动作

操作含义
it = container.begin()取得起始位置的迭代器
it != container.end()判断是否结束
++it移动到下一个元素
*it获取当前指向的元素
std::vector<int> nums = {5, 10, 15};
for (auto it = nums.begin(); it != nums.end(); ++it) {std::cout << *it << " ";
}
操作说明
--it移动到上一个元素(双向或更强迭代器)
it == it2, it != it2比较两个迭代器
it + n, it - n随机访问(仅支持随机访问迭代器)
std::distance(it1, it2)两个迭代器之间的距离
std::advance(it, n)将迭代器移动 n 个位置(支持不同迭代器类型)

🚸 初学者推荐写法:使用 auto范围for

从 C++11 开始,可以让写法更简单!

✅ 用 auto 简化迭代器声明:

for (auto it = nums.begin(); it != nums.end(); ++it)

✅ 更简单的方法:范围for(推荐):

范围 for 是 C++11 引入的一种简洁写法,用于遍历容器或数组。它让你不需要写迭代器、不需要用下标,直接访问每一个元素。 

for (元素类型 变量名 : 容器) {// 使用变量名代表当前元素
}

传统写法(使用迭代器): 

std::vector<int> v = {1, 2, 3, 4};
for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {std::cout << *it << "\n";
}

 范围 for 写法:

std::vector<int> v = {1, 2, 3, 4};
for (int x : v) {std::cout << x << "\n";
}

 范围 for 背后的原理:

for (auto it = v.begin(); it != v.end(); ++it) {int x = *it;...
}

所以它仍然依赖迭代器,只不过帮你“自动写好了”。

http://www.xdnf.cn/news/355951.html

相关文章:

  • 【软件测试】测试用例的设计方法
  • Kafka集群加入新Broker节点会发生什么
  • 在Cline上调用MCP服务之MCP实践篇
  • Vue Baidu Map
  • 学习记录:DAY28
  • Xcode16.3配置越狱开发环境
  • 武汉火影数字|数字科技馆打造:开启科技探索新大门
  • 深入理解 Java 代理模式:从基础到实战​
  • BP神经网络
  • 【PmHub后端篇】PmHub整合TransmittableThreadLocal (TTL)缓存用户数据
  • Python代码编程基础
  • 使用JMETER中的JSON提取器实现接口关联
  • onResume()和 onPause()的触发条件
  • 7、三维机械设计、装配与运动仿真组件 - /设计与仿真组件/3d-mechanical-designer
  • c/c++的Libevent 和OpenSSL构建HTTPS客户端详解(附带源码)
  • 基于设备指纹识别的反爬虫技术:给设备办 “身份证”
  • 【MySQL】-- 事务
  • 机器学习之数据转换策略
  • Java 23种设计模式 - 结构型模式7种
  • 数据库故障排查指南
  • React+Taro选择日期组件封装
  • 51c自动驾驶~合集40
  • 新品:同等小体积通信距离翻一倍-RF3060F27通信模块
  • Vmware 最新下载教程和安装教程,外带免下载文件
  • project从入门到精通(四)
  • idea spring boot 打包成可执行的 JAR包
  • 使用docker安装Dinky
  • `timescale 1ns/1ps的意义
  • 【250GB空间不够用】
  • 发那科机器人4(编程实例)