C++ 迭代器类别
迭代器概述
在C++标准模板库(STL)中,迭代器是连接算法和容器的桥梁。它们提供了一种访问容器中元素的统一方式,使得算法可以不依赖于具体容器类型而工作。根据功能和特性的不同,C++将迭代器分为五个主要类别,每种类别都支持不同的操作集合。
五种迭代器类别
1. 输入迭代器(Input Iterator)
输入迭代器是最基础的迭代器类型,它支持从容器中读取数据并向前移动。
特性:
- 只能 单次遍历容器
- 只读访问元素
- 支持相等/不相等比较
- 支持前缀和后缀递增操作
- 支持解引用操作(只读)
典型用法:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用输入迭代器来读取元素
std::vector<int>::iterator it = numbers.begin();
while (it != numbers.end()) {
std::cout << *it << " ";
++it;
}
// 输出: 1 2 3 4 5
return 0;
}
2. 输出迭代器(Output Iterator)
输出迭代器允许向容器写入数据。它与输入迭代器正好相反。
特性:
- 只能单次遍历容器
- 只写访问元素
- 支持前缀和后缀递增操作
- 支持解引用操作(只写)
典型用法:
#include <iostream>
#include <vector>
#include <iterator>
int main() {
std::vector<int> numbers(5);
// 使用输出迭代器向容器写入数据
std::fill_n(numbers.begin(), 5, 10);
// 输出结果验证
for (int num : numbers) {
std::cout << num << " ";
}
// 输出: 10 10 10 10 10
return 0;
}
3. 前向迭代器(Forward Iterator)
前向迭代器结合了输入和输出迭代器的功能,可以多次遍历容器,但只能向前移动。
特性:
- 可多次遍历容器
- 支持读写访问元素
- 支持相等/不相等比较
- 支持前缀和后缀递增操作
典型用法:
#include <iostream>
#include <forward_list>
int main() {
std::forward_list<int> numbers = {1, 2, 3, 4, 5};
// 使用前向迭代器读取和修改元素
std::forward_list<int>::iterator it = numbers.begin();
while (it != numbers.end()) {
*it = *it * 2; // 修改元素
++it;
}
// 再次遍历查看修改后的结果
for (int num : numbers) {
std::cout << num << " ";
}
// 输出: 2 4 6 8 10
return 0;
}
4. 双向迭代器(Bidirectional Iterator)
双向迭代器在前向迭代器的基础上增加了向后移动的能力。
特性:
- 可多次遍历容器
- 支持读写访问元素
- 支持相等/不相等比较
- 支持前缀和后缀递增、递减操作
典型用法:
#include <iostream>
#include <list>
int main() {
std::list<int> numbers = {1, 2, 3, 4, 5};
// 使用双向迭代器向前和向后移动
std::list<int>::iterator it = numbers.begin();
// 向前移动到末尾前一个元素
++it; ++it; ++it; ++it; // 现在指向5
// 向后移动
std::cout << "向后遍历: ";
while (it != numbers.begin()) {
std::cout << *it << " ";
--it;
}
std::cout << *it << std::endl;
// 输出: 向后遍历: 5 4 3 2 1
return 0;
}
5. 随机访问迭代器(Random Access Iterator)
随机访问迭代器是功能最强大的迭代器类型,它允许对容器中的任意元素进行直接访问。
特性:
- 支持双向迭代器的所有操作
- 支持迭代器算术运算(如加减操作)
- 支持迭代器与整数的加减运算
- 支持下标操作符
[]
- 支持关系运算符
(<, >, <=, >=)
典型用法:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {10, 20, 30, 40, 50};
// 使用随机访问迭代器
std::vector<int>::iterator it = numbers.begin();
// 直接跳转到第三个元素
it += 2;
std::cout << "第三个元素: " << *it << std::endl; // 输出: 30
// 使用下标访问
std::cout << "第四个元素: " << it[1] << std::endl; // 输出: 40
// 元素比较
std::vector<int>::iterator it2 = numbers.begin();
if (it > it2) {
std::cout << "it指向的位置在it2之后" << std::endl;
}
// 计算两个迭代器之间的距离
std::cout << "距离: " << it - it2 << std::endl; // 输出: 2
return 0;
}
容器与迭代器类别对应关系
下面是常见STL容器所支持的迭代器类别:
容器 | 迭代器类别 |
---|---|
vector | 随机访问迭代器 |
array | 随机访问迭代器 |
deque | 随机访问迭代器 |
list | 双向迭代器 |
forward_list | 前向迭代器 |
set/multiset | 双向迭代器 |
map/multimap | 双向迭代器 |
unordered_set | 前向迭代器 |
unordered_map | 前向迭代器 |
提示
记住这个对应关系对于选择合适的算法和容器组合非常有帮助!
实际应用场景
场景一:数据处理管道
假设我们需要处理一个整数列表:筛选出偶数,将它们乘以2,然后计算总和。
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::vector<int> evenNumbers;
// 使用输出迭代器将偶数筛选到新容器
std::copy_if(numbers.begin(), numbers.end(),
std::back_inserter(evenNumbers),
[](int n) { return n % 2 == 0; });
// 使用双向迭代器修改元素
std::transform(evenNumbers.begin(), evenNumbers.end(),
evenNumbers.begin(),
[](int n) { return n * 2; });
// 使用输入迭代器计算总和
int sum = std::accumulate(evenNumbers.begin(), evenNumbers.end(), 0);
std::cout << "处理后的数组: ";
for (int num : evenNumbers) {
std::cout << num << " ";
}
std::cout << "\n总和: " << sum << std::endl;
// 输出:
// 处理后的数组: 4 8 12 16 20
// 总和: 60
return 0;
}