元素码农
基础
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:21
↑
☰
# C++ 迭代器适配器详解 迭代器适配器是C++标准库提供的一组工具,用于转换或扩展现有迭代器的功能。本文将详细介绍C++中的主要迭代器适配器类型,包括它们的特点、实现原理和使用场景。 ## 主要迭代器适配器类型 ### 反向迭代器(reverse_iterator) 反向迭代器将双向或随机访问迭代器的遍历方向反转。 #### 特点 - 将递增操作转换为递减 - 将递减操作转换为递增 - 保持原迭代器的其他功能 - 需要原迭代器支持双向遍历 #### 实现原理 ```cpp template <class Iterator> class reverse_iterator { protected: Iterator current; // 原始迭代器 public: using iterator_type = Iterator; using difference_type = typename iterator_traits<Iterator>::difference_type; using value_type = typename iterator_traits<Iterator>::value_type; using pointer = typename iterator_traits<Iterator>::pointer; using reference = typename iterator_traits<Iterator>::reference; reference operator*() const { Iterator tmp = current; return *--tmp; // 返回前一个位置的元素 } reverse_iterator& operator++() { --current; // 递增转换为递减 return *this; } // ... }; ``` #### 使用示例 ```cpp #include <vector> #include <iterator> std::vector<int> vec = {1, 2, 3, 4, 5}; // 使用反向迭代器 std::reverse_iterator<std::vector<int>::iterator> rbegin(vec.end()); std::reverse_iterator<std::vector<int>::iterator> rend(vec.begin()); // 或者直接使用容器的rbegin/rend for(auto it = vec.rbegin(); it != vec.rend(); ++it) { std::cout << *it << " "; // 输出: 5 4 3 2 1 } ``` ### 插入迭代器(insert_iterator) 插入迭代器将赋值操作转换为容器的插入操作。 #### 类型 1. back_insert_iterator - 在容器末尾插入元素 - 容器必须支持push_back 2. front_insert_iterator - 在容器开头插入元素 - 容器必须支持push_front 3. insert_iterator - 在指定位置插入元素 - 容器必须支持insert #### 实现原理 ```cpp template <class Container> class back_insert_iterator { protected: Container* container; // 目标容器 public: using container_type = Container; explicit back_insert_iterator(Container& x) : container(&x) {} back_insert_iterator& operator=(const typename Container::value_type& value) { container->push_back(value); return *this; } back_insert_iterator& operator*() { return *this; } back_insert_iterator& operator++() { return *this; } back_insert_iterator operator++(int) { return *this; } }; ``` #### 使用示例 ```cpp #include <vector> #include <list> #include <iterator> // back_insert_iterator示例 std::vector<int> vec; std::back_insert_iterator<std::vector<int>> back_it(vec); *back_it = 1; // vec: {1} *back_it = 2; // vec: {1, 2} // 使用便捷函数back_inserter std::copy(src.begin(), src.end(), std::back_inserter(vec)); // front_insert_iterator示例 std::list<int> lst; std::front_insert_iterator<std::list<int>> front_it(lst); *front_it = 1; // lst: {1} *front_it = 2; // lst: {2, 1} // insert_iterator示例 std::vector<int> vec2 = {1, 2, 3}; std::insert_iterator<std::vector<int>> insert_it(vec2, vec2.begin() + 1); *insert_it = 10; // vec2: {1, 10, 2, 3} ``` ### 流迭代器(stream_iterator) 流迭代器将输入/输出流转换为迭代器接口。 #### 类型 1. istream_iterator - 从输入流读取数据 - 实现输入迭代器要求 2. ostream_iterator - 向输出流写入数据 - 实现输出迭代器要求 #### 实现原理 ```cpp template <class T, class CharT = char, class Traits = char_traits<CharT>> class istream_iterator { protected: basic_istream<CharT, Traits>* in_stream; T value; // 当前值 public: using iterator_category = input_iterator_tag; using value_type = T; istream_iterator() : in_stream(nullptr) {} istream_iterator(basic_istream<CharT, Traits>& s) : in_stream(&s) { ++*this; // 读取第一个值 } const T& operator*() const { return value; } istream_iterator& operator++() { if(in_stream && !(*in_stream >> value)) { in_stream = nullptr; } return *this; } }; ``` #### 使用示例 ```cpp #include <iterator> #include <iostream> #include <algorithm> // istream_iterator示例 std::istream_iterator<int> input(std::cin); std::istream_iterator<int> end; std::vector<int> numbers; std::copy(input, end, std::back_inserter(numbers)); // ostream_iterator示例 std::ostream_iterator<int> output(std::cout, " "); std::copy(numbers.begin(), numbers.end(), output); ``` ### 移动迭代器(move_iterator) 移动迭代器将解引用操作转换为移动语义。 #### 特点 - 支持C++11移动语义 - 避免不必要的拷贝 - 原迭代器的值可能被移动后失效 #### 实现原理 ```cpp template <class Iterator> class move_iterator { protected: Iterator current; // 原始迭代器 public: using iterator_type = Iterator; using value_type = typename iterator_traits<Iterator>::value_type; move_iterator(Iterator i) : current(i) {} reference operator*() const { return std::move(*current); } move_iterator& operator++() { ++current; return *this; } }; ``` #### 使用示例 ```cpp #include <vector> #include <string> #include <iterator> std::vector<std::string> src = {"hello", "world"}; std::vector<std::string> dest; // 使用移动迭代器进行移动而不是拷贝 std::copy(std::make_move_iterator(src.begin()), std::make_move_iterator(src.end()), std::back_inserter(dest)); // src中的字符串现在可能为空 ``` ## 最佳实践 1. 选择合适的适配器 - 需要反向遍历 -> reverse_iterator - 需要插入操作 -> insert_iterator系列 - 需要流操作 -> stream_iterator - 需要移动语义 -> move_iterator 2. 使用便捷函数 - rbegin/rend代替手动构造reverse_iterator - back_inserter/front_inserter/inserter代替手动构造insert_iterator - make_move_iterator代替手动构造move_iterator 3. 注意性能 - 插入迭代器可能导致多次内存重分配 - 流迭代器可能影响I/O性能 - 移动迭代器可能使源对象失效 4. 迭代器要求 - reverse_iterator需要双向迭代器 - insert_iterator需要容器支持对应的插入操作 - stream_iterator需要流支持对应的操作 ## 常见陷阱 1. 反向迭代器的位置 - base()返回的是下一个位置 - 解引用操作返回前一个位置的值 2. 插入迭代器的副作用 - 可能导致容器重新分配内存 - 可能使现有迭代器失效 3. 流迭代器的状态 - 流错误会使迭代器变为end迭代器 - 需要正确处理流的错误状态 4. 移动迭代器的影响 - 源对象可能被移动后处于有效但未指定状态 - 不应再访问被移动的对象 ## 总结 C++标准库的迭代器适配器提供了强大的工具,可以方便地扩展和转换迭代器的功能。通过使用这些适配器,我们可以更灵活地操作容器、流和其他数据结构。理解每种适配器的特点和使用场景,有助于我们编写更简洁、高效的代码。在实际使用中,应该根据具体需求选择合适的适配器,并注意避免常见的陷阱。