3人参与 • 2026-08-07 • C/C++
迭代器(iterator)是 c++ stl 的核心组件,被称为容器与算法之间的万能桥梁。它是一种用于遍历、访问stl容器元素的抽象接口,能够统一操作不同底层结构的容器,彻底屏蔽各类容器的底层实现差异。
简单来说:迭代器是面向容器的"智能指针",用法和指针高度相似,但功能更强大、安全性更高,是操作vector、list、map、set等所有stl容器的标准方式。
c++ stl的核心设计思想是数据与算法分离:
不同容器底层存储结构完全不同,如果没有迭代器,每种容器都需要配套专属的遍历、操作算法,代码冗余度极高。而迭代器提供了统一的访问接口,一套算法可以适配所有容器,极大提升代码复用性与通用性。
| 特性 | 普通指针 | stl迭代器 |
|---|---|---|
| 适用范围 | 仅适配连续内存空间(数组) | 适配所有stl容器(连续/非连续内存) |
| 安全性 | 无边界检查,易越界报错 | 自带容器边界约束,安全性更高 |
| 功能拓展 | 仅支持解引用、自增自减 | 支持遍历、定位、反向访问、常量访问等 |
| 底层依赖 | 内存地址直接操作 | 封装容器底层访问逻辑,屏蔽细节 |
c++标准根据迭代器的操作能力强弱,将其分为5类,能力由弱到强逐级递增,低阶迭代器的所有特性高阶迭代器全部兼容。不同容器适配的迭代器类型不同,直接决定容器支持的算法操作。
核心特性:只读、单向遍历,仅支持 ++ 自增,不支持反向、随机访问,仅能单遍扫描数据。
典型场景:std::find、std::accumulate 等只读算法,istream_iterator(输入流迭代器)。
核心特性:只写、单向遍历,仅支持 ++ 自增,只能修改元素,无法读取元素值。
典型场景:std::copy、std::fill 等写入算法,ostream_iterator(输出流迭代器)。
核心特性:可读可写、单向遍历,支持 ++ 自增,可多次遍历容器,可保存迭代器状态。
适配容器:unordered_set、unordered_map 等哈希容器。
核心特性:可读可写、双向遍历,支持 ++ 自增、-- 自减,可前后移动访问元素。
适配容器:list、set、map、multiset、multimap。
核心特性:最强迭代器,兼容所有双向迭代器特性,支持随机跳跃访问。
支持操作:it + n、it - n、it1 - it2、大小比较 >/</==。
适配容器:vector、string、deque(连续内存容器)。
面试考点:为什么list不支持sort随机排序?因为list仅支持双向迭代器,不支持随机访问,无法使用
std::sort算法,只能使用自身专属sort方法。
所有stl容器都提供两个最基础的迭代器获取方法:
begin():返回指向容器第一个元素的迭代器end():返回指向容器末尾下一个位置的迭代器(哨兵位,不存储有效数据,不可解引用)遍历通用规则:从 begin() 开始,到 end() 结束,循环自增迭代器。
可读可写,可修改容器内元素值。
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec = {1, 2, 3, 4, 5};
// 定义vector普通迭代器
vector<int>::iterator it;
// 遍历容器并修改元素
for (it = vec.begin(); it != vec.end(); ++it) {
*it *= 2; // 解引用修改元素
cout << *it << " ";
}
return 0;
}
只读不可写,禁止修改容器元素,适合仅遍历读取的场景,安全性更高。
vector<int> vec = {1, 2, 3, 4, 5};
// 常量迭代器,只读
vector<int>::const_iterator cit;
for (cit = vec.cbegin(); cit != vec.cend(); ++cit) {
cout << *cit << " ";
// *cit = 10; 报错!常量迭代器无法修改元素
}
补充:cbegin()、cend() 是c++11新增方法,专门返回常量迭代器。
实现倒序遍历容器,从末尾元素遍历到首元素。对应配套方法:rbegin()、rend()。
vector<int> vec = {1, 2, 3, 4, 5};
vector<int>::reverse_iterator rit;
// 倒序遍历
for (rit = vec.rbegin(); rit != vec.rend(); ++rit) {
cout << *rit << " "; // 输出:5 4 3 2 1
}
倒序只读遍历,无法修改元素,用法结合反向迭代器与常量迭代器特性。
*it:解引用,获取迭代器指向的元素值++it / it++:迭代器向后移动一位(推荐前置++,效率更高)--it / it--:迭代器向前移动一位(仅双向/随机迭代器支持)it + n / it - n:跳跃移动(仅随机访问迭代器支持)it1 == it2 / it1 != it2:判断迭代器是否指向同一位置(所有迭代器支持)c++11及以上版本支持auto关键字,无需手写冗长的迭代器类型,代码更简洁。
vector<int> vec = {10, 20, 30, 40};
// auto自动推导普通迭代器
for (auto it = vec.begin(); it != vec.end(); ++it) {
cout << *it << " ";
}
// auto推导常量迭代器(只读)
for (auto cit = vec.cbegin(); cit != vec.cend(); ++cit) {
cout << *cit << " ";
}
日常开发最常用的遍历方式,底层完全基于迭代器实现,语法极简。
vector<int> vec = {1, 3, 5, 7, 9};
// 只读遍历
for (int val : vec) {
cout << val << " ";
}
// 可修改遍历(加引用)
for (int& val : vec) {
val += 1;
cout << val << " ";
}
注意:范围for仅适合完整遍历容器,无法实现跳跃、定点遍历,复杂场景仍需原生迭代器。
迭代器本质是对容器元素位置的记录,当容器发生扩容、删除、清空等操作时,容器底层内存结构改变,原有迭代器记录的地址失效,继续使用会导致程序崩溃、数据错乱。
仅被删除元素的迭代器失效,其余迭代器全部有效(链表结构,删除仅修改节点指针,不影响其他节点)。
插入元素:所有迭代器有效;删除元素:仅被删除节点迭代器失效,其余有效。
核心思路:操作容器后,重新获取迭代器,或使用容器操作的返回值更新迭代器。
错误示例(遍历删除导致失效崩溃):
vector<int> vec = {1, 2, 2, 3, 2};
// 错误写法!删除后迭代器失效
for (auto it = vec.begin(); it != vec.end(); ++it) {
if (*it == 2) {
vec.erase(it); // 失效!后续迭代器无法正常遍历
}
}
正确示例(利用erase返回值更新迭代器):
vector<int> vec = {1, 2, 2, 3, 2};
for (auto it = vec.begin(); it != vec.end();) {
if (*it == 2) {
// erase返回删除元素的下一个有效迭代器
it = vec.erase(it);
} else {
++it;
}
}
stl算法的所有接口全部依赖迭代器,通过迭代器传递容器数据,实现通用数据处理。
#include <iostream>
#include <vector>
#include <algorithm> // stl算法头文件
using namespace std;
int main() {
vector<int> vec = {5, 2, 9, 1, 5, 6};
// 1. 排序算法:[begin, end) 左闭右开区间
sort(vec.begin(), vec.end());
// 2. 查找元素
auto pos = find(vec.begin(), vec.end(), 9);
if (pos != vec.end()) {
cout << "找到元素:" << *pos << endl;
}
// 3. 遍历输出
for (auto val : vec) {
cout << val << " ";
}
return 0;
}
以上就是c++ stl迭代器从原理到实战的完全指南的详细内容,更多关于c++ stl迭代器完全指南的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论