元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
C++基础
▶
类型系统
基本数据类型
类型推导
类型转换
▶
编译模型
翻译单元
ODR规则
头文件与实现分离
▶
作用域与生命周期
存储期类型
RAII机制
对象构造与析构
▶
面向对象编程
▶
类设计
成员访问控制
特殊成员函数
友元机制
▶
继承体系
虚函数表
多重继承
虚继承
▶
多态实现
动态绑定
RTTI机制
类型擦除
▶
模板与泛型编程
▶
模板基础
函数模板
类模板
可变参数模板
▶
模板元编程
SFINAE
类型萃取
编译期计算
▶
概念与约束
requires表达式
概念定义
约束模板
▶
内存模型
▶
内存管理
堆与栈
智能指针
移动语义
▶
对象模型
成员布局
虚函数实现
空基类优化
▶
并发内存
内存顺序
原子操作
内存屏障
▶
标准库核心
▶
容器
序列容器
关联容器
无序容器
▶
迭代器
迭代器类别
迭代器适配器
范围迭代
▶
函数对象
函数包装器
绑定表达式
lambda实现
发布时间:
2025-03-23 10:20
↑
☰
# C++ 迭代器类别详解 迭代器是C++标准库的核心概念之一,它提供了一种统一的方式来访问和遍历容器中的元素。本文将详细介绍C++中的迭代器类别,包括它们的特点、要求和使用场景。 ## 迭代器类别概述 C++标准库定义了五种主要的迭代器类别,每种类别都有特定的功能要求和操作保证: 1. 输入迭代器(Input Iterator) 2. 输出迭代器(Output Iterator) 3. 前向迭代器(Forward Iterator) 4. 双向迭代器(Bidirectional Iterator) 5. 随机访问迭代器(Random Access Iterator) 这些类别形成了一个层次结构,每个后继类别都包含前一个类别的所有功能。 ## 输入迭代器 输入迭代器是最基本的迭代器类型,用于从容器中读取元素。 ### 要求 - 只读访问 - 单遍访问 - 只能递增 - 支持相等比较 ### 操作 ```cpp *it // 读取元素 it->member // 访问成员 ++it // 前置递增 it++ // 后置递增 it1 == it2 // 相等比较 it1 != it2 // 不等比较 ``` ### 示例 ```cpp #include <iterator> #include <iostream> void print_stream(std::istream& is) { // istream_iterator是输入迭代器的例子 std::istream_iterator<int> it(is); std::istream_iterator<int> end; while(it != end) { std::cout << *it << " "; ++it; } } ``` ## 输出迭代器 输出迭代器用于向容器写入元素。 ### 要求 - 只写访问 - 单遍访问 - 只能递增 ### 操作 ```cpp *it = value // 写入元素 ++it // 前置递增 it++ // 后置递增 ``` ### 示例 ```cpp #include <iterator> #include <vector> void write_numbers(std::vector<int>& vec) { // back_insert_iterator是输出迭代器的例子 std::back_insert_iterator<std::vector<int>> it(vec); for(int i = 0; i < 5; ++i) { *it = i; // 等价于vec.push_back(i) ++it; } } ``` ## 前向迭代器 前向迭代器支持多遍访问和前向遍历。 ### 要求 - 读写访问 - 多遍访问 - 只能向前遍历 - 支持相等比较 ### 操作 ```cpp *it // 读写元素 it->member // 访问成员 ++it // 前置递增 it++ // 后置递增 it1 == it2 // 相等比较 it1 != it2 // 不等比较 ``` ### 示例 ```cpp #include <forward_list> void process_list(std::forward_list<int>& lst) { // forward_list的迭代器是前向迭代器 auto it = lst.begin(); while(it != lst.end()) { if(*it % 2 == 0) { *it *= 2; // 可以修改元素 } ++it; } } ``` ## 双向迭代器 双向迭代器支持双向遍历。 ### 要求 - 读写访问 - 多遍访问 - 可以双向遍历 - 支持相等比较 ### 操作 ```cpp *it // 读写元素 it->member // 访问成员 ++it // 前置递增 it++ // 后置递增 --it // 前置递减 it-- // 后置递减 it1 == it2 // 相等比较 it1 != it2 // 不等比较 ``` ### 示例 ```cpp #include <list> void reverse_process(std::list<int>& lst) { // list的迭代器是双向迭代器 auto it = lst.end(); while(it != lst.begin()) { --it; *it *= 2; // 可以修改元素 } } ``` ## 随机访问迭代器 随机访问迭代器提供了最完整的功能,支持随机访问和迭代器算术运算。 ### 要求 - 读写访问 - 多遍访问 - 随机访问 - 支持迭代器算术 - 支持关系运算 ### 操作 ```cpp *it // 读写元素 it->member // 访问成员 ++it // 前置递增 it++ // 后置递增 --it // 前置递减 it-- // 后置递减 it += n // 前进n个位置 it -= n // 后退n个位置 it + n // 返回前进n个位置的迭代器 it - n // 返回后退n个位置的迭代器 it1 - it2 // 计算迭代器之间的距离 it[n] // 访问偏移位置的元素 it1 < it2 // 比较迭代器位置 it1 <= it2 it1 > it2 it1 >= it2 ``` ### 示例 ```cpp #include <vector> void random_access(std::vector<int>& vec) { // vector的迭代器是随机访问迭代器 auto it = vec.begin(); // 随机访问 it += 5; // 直接跳转到第6个元素 // 使用下标操作 for(int i = 0; i < vec.size(); ++i) { vec.begin()[i] *= 2; } // 计算距离 auto dist = vec.end() - vec.begin(); // 获取容器大小 } ``` ## 迭代器类别与容器 不同的容器提供不同类别的迭代器: | 容器 | 迭代器类别 | |------|------------| | vector | 随机访问 | | deque | 随机访问 | | array | 随机访问 | | list | 双向 | | set/map | 双向 | | forward_list | 前向 | | unordered_set/map | 前向 | ## 迭代器特征 C++标准库提供了iterator_traits来获取迭代器的特征: ```cpp template <class Iterator> struct iterator_traits { using difference_type = typename Iterator::difference_type; using value_type = typename Iterator::value_type; using pointer = typename Iterator::pointer; using reference = typename Iterator::reference; using iterator_category = typename Iterator::iterator_category; }; ``` ### 使用示例 ```cpp #include <iterator> #include <type_traits> template <typename Iterator> void algorithm(Iterator first, Iterator last) { // 获取迭代器类别 using category = typename std::iterator_traits<Iterator>::iterator_category; // 根据类别选择不同的实现 if constexpr (std::is_same_v<category, std::random_access_iterator_tag>) { // 使用随机访问优化版本 } else { // 使用通用版本 } } ``` ## 最佳实践 1. 选择合适的迭代器类别 - 如果只需要单次遍历和读取,使用输入迭代器 - 如果只需要写入,使用输出迭代器 - 如果需要多次遍历但只向前,使用前向迭代器 - 如果需要双向遍历,使用双向迭代器 - 如果需要随机访问,使用随机访问迭代器 2. 算法设计 - 尽可能使用最弱的迭代器要求 - 根据迭代器类别提供优化的实现 - 使用iterator_traits获取迭代器特征 3. 迭代器失效 - 注意容器操作可能导致迭代器失效 - 在修改容器后更新失效的迭代器 - 使用安全的迭代方式 ## 总结 C++的迭代器类别系统提供了一个灵活而强大的抽象,允许我们编写通用的算法,同时又能根据具体迭代器的能力进行优化。理解不同迭代器类别的特点和要求,有助于我们选择合适的容器,并编写高效的算法。在实际编程中,应该根据需求选择最合适的迭代器类别,并注意处理迭代器失效的问题。