简介
迭代器是 C++ 的一个重要组成部分, 它在数据结构和算法之间架起了桥梁. 迭代器作为通用指针, 可以遍历和操作容器中的元素, 同时隐藏底层的复杂性. 让我们一起探索现代 C++ 中迭代器的概念, 类别和使用场景.
什么是迭代器?
迭代器是一种抽象工具, 它允许顺序访问集合中的元素, 而无需暴露集合的底层实现. 迭代器是指针的泛化, 使得可以遍历数组, 向量, 列表等容器.
示例:
std::vector<int> vec{10, 20, 30, 40};
for (auto it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << " ";
}
// 输出: 10 20 30 40
相比较而言, 传统的访问方式为:
for (size_t i = 0; i < vec.size(); i++) {std::cout << vec[i] << " ";
}
std::cout << std::endl;auto p = vec.data();
for (size_t i = 0; i < vec.size(); i++) {std::cout << p[i] << " ";
}
std::cout << std::endl;
迭代器类别
C++ 定义了多个迭代器类别, 每种类别具备不同的能力.
-  随机访问迭代器(Random Access Iterators): 支持完全的随机访问, 比较和算术操作. - 容器: std::vector,std::array, 原生数组.
- 操作: ++, --, +=, -=, *, [], <, <=, >, >=
 #include <iostream> #include <vector>int main() {std::vector<int> vec{0, 1, 2, 3, 4, 5, 6, 7, 8};auto it = vec.begin();it++;it += 3;std::cout << *it << std::endl; // 4std::cout << it[0] << std::endl; // 4auto it2 = vec.begin() + 6;std::cout << std::boolalpha << (it < it2) << std::endl; // true }
- 容器: 
-  双向迭代器(Bidirectional Iterators): 支持向前和向后遍历. - 容器: 链表(std::list), 关联容器如std::set,std::map.
- 操作: ++, --, *, ==, !=
 #include <iostream> #include <list>int main() {std::list<int> vec{0, 1, 2, 3, 4, 5, 6, 7, 8};auto it = vec.begin();it++;std::cout << *it << std::endl; // 1it--;std::cout << *it << std::endl; // 0 }
- 容器: 链表(
-  前向迭代器(Forward Iterators): 仅支持单向遍历. - 容器: std::forward_list, 无序关联容器std::unordered_map,std::unordered_set
- 操作: ++, *, ==, !=
 #include <iostream> #include <unordered_map>int main() {std::unordered_map<int, int> map{{1, 2}, {3, 4}, {5, 6}};auto it = map.begin();it++;// it--; // Errorstd::cout << it->first << ": " << it->second << std::endl; // 3: 4 }
- 容器: 
-  输入迭代器(Input Iterators): 设计用于一次性读取. - 示例: std::istream_iterator
 
- 示例: 
-  输出迭代器(Output Iterators): 用于一次性写入到范围. - 示例: std::ostream_iterator
 
- 示例: 
半开区间和安全性
迭代器遵循半开区间约定, 范围从 begin() 开始, 到 end() 前结束. 这种设计防止了越界访问.
示例:
std::vector<int> nums{1, 2, 3, 4};
for (auto it = nums.begin(); it != nums.end(); ++it) {std::cout << *it << " ";
}
STL 算法中的迭代器
标准模板库(STL)的算法利用迭代器实现与容器无关的操作. 例如:
-  查找元素: auto it = std::find(vec.begin(), vec.end(), value); if (it != vec.end()) {std::cout << "找到: " << *it; }
-  转换元素: std::transform(src.begin(), src.end(), dest.begin(), [](int x) { return x * x; });
需要避免的陷阱
- 悬空迭代器: 修改容器(如调整大小或添加元素)可能会使现有的迭代器失效.
- 迭代器不匹配: 比较来自不同容器的迭代器会导致未定义行为.
未定义行为示例:
-  在获取迭代器之后修改容器元素. std::vector<int> vec{1, 2, 3}; auto it = vec.begin(); vec.push_back(4); std::cout << *it; // 未定义行为: 迭代器失效
-  在遍历容器的时候删除迭代器 void remove(std::vector<int>& vec, int target) {for (auto it = vec.begin(); it != vec.end(); it++) {if (*it == target) {vec.erase(it);}} }
现代增强
-  基于范围的循环(C++11), 使用 for循环简化迭代:for (const auto& elem : vec) {std::cout << elem << " "; }
-  视图与过滤器(C++20), 引入对范围的惰性评估. auto filtered = vec | std::views::filter([](int x) { return x > 10; }); for (int val : filtered) {std::cout << val << " "; }
总结
C++ 迭代器在数据结构和算法之间起着关键作用, 提供了灵活性和强大功能. 理解它们的类别, 正确用法和可能的陷阱, 可以确保高效且无错误的编程. 拥抱现代增强特性, 简化并优化您的代码!