C++迭代器全解析:从概念到实践,掌握STL的灵魂

5 阅读4分钟

C++ 迭代器全解析:从概念到实践,掌握 STL 的灵魂

迭代器(Iterator)是 STL 的核心灵魂,它统一了所有容器的遍历方式,让 vector、list、map、set 等不同数据结构,能用同一套语法遍历、访问、修改,彻底屏蔽底层实现差异。

这篇会从概念 → 分类 → 原理 → 实战 → 手写迭代器,彻底讲透。


一、迭代器是什么?(一句话理解)

迭代器就是指向容器元素的“智能指针”

  • 行为像指针:支持 ​​*it​​、​​++it​​、​​--it​​、​​->​
  • 作用:遍历容器 + 访问元素,不关心容器底层是数组、链表还是树
  • 语法统一:所有 STL 容器遍历代码几乎一模一样

没有迭代器,vector 用下标、list 用节点指针、map 用二叉树指针,代码会彻底混乱。


二、迭代器核心语法(所有容器通用)

// 1. 获取迭代器
auto it = container.begin();   // 指向第一个元素
auto end = container.end();     // 指向【最后一个元素的下一个位置】

// 2. 通用遍历(最标准写法)
for (auto it = vec.begin(); it != vec.end(); ++it) {
    cout << *it << endl;    // 解引用访问元素
}

// 3. 范围for(本质就是迭代器语法糖)
for (auto& x : container) { ... }

关键规则

  • ​end()​​ 不是最后一个元素,不能解引用
  • 优先用 ​​++it​​ 而不是 ​​it++​​(更高效)
  • 只读遍历用 ​​const_iterator​

三、迭代器的 5 种分类(必须掌握)

功能强弱排序,越往下功能越强:

1. 输入迭代器(Input)

只能读一次,单向遍历 例:​​istream_iterator​

2. 输出迭代器(Output)

只能写一次,单向遍历 例:​​ostream_iterator​

3. 前向迭代器(Forward)

可多次读写,只能向前走 例:​​forward_list​

4. 双向迭代器(Bidirectional)

支持 ​​++​​ 和 ​​--​​,可前进可后退 例:​​list / map / set​

5. 随机访问迭代器(Random Access)

最强!支持 ​​+ - [] < >​​ 等所有运算 例:​​vector / deque / 原生数组​

map/set 都是双向迭代器,不支持 it+5 这种跳跃操作!


四、迭代器常用配套工具(STL 标准)

#include <iterator>
advance(it, n);      // 让迭代器前进 n 步(通用所有迭代器)
next(it);            // 下一个元素
prev(it);            // 上一个元素
distance(it1, it2);   // 两个迭代器之间的元素个数

这些函数自动适配迭代器类型,随机访问 O(1),双向 O(n)。


五、实战:4 大容器迭代器遍历(代码完全统一)

你会发现写法几乎一模一样,这就是迭代器的威力!

#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
using namespace std;

int main() {
    // 1. vector(随机访问迭代器)
    vector<int> vec = {1,2,3};
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        cout << *it << " ";
    }

    // 2. list(双向迭代器)
    list<int> lst = {1,2,3};
    for (auto it = lst.begin(); it != lst.end(); ++it) {
        cout << *it << " ";
    }

    // 3. set(双向迭代器)
    set<int> st = {1,2,3};
    for (auto it = st.begin(); it != st.end(); ++it) {
        cout << *it << " ";
    }

    // 4. map(双向迭代器,key-value)
    map<int, string> mp = {{1,"a"},{2,"b"}};
    for (auto it = mp.begin(); it != mp.end(); ++it) {
        cout << it->first << ":" << it->second << " ";
    }
    return 0;
}

六、const_iterator & 反向迭代器

1. const_iterator

只读迭代器,不能修改元素

vector<int>::const_iterator it;
for (auto it = vec.cbegin(); it != vec.cend(); ++it) {
    // *it = 10; 错误!只读
}

2. reverse_iterator

反向遍历,从尾到头

for (auto it = vec.rbegin(); it != vec.rend(); ++it) {
    cout << *it << " ";
}

七、进阶:手写一个简易迭代器(理解底层原理)

迭代器本质就是封装指针/节点,重载运算符。 我们给一个简单数组实现迭代器:

#include <iostream>
using namespace std;

// 模拟一个简单数组容器
class MyVector {
private:
    int* arr;
    int size;
public:
    MyVector(int* a, int s) : arr(a), size(s) {}

    // 迭代器:封装原生指针
    typedef int* iterator;

    // begin / end
    iterator begin() { return arr; }
    iterator end() { return arr + size; }
};

int main() {
    int arr[] = {10,20,30};
    MyVector vec(arr, 3);

    // 使用迭代器遍历
    for (MyVector::iterator it = vec.begin(); it != vec.end(); ++it) {
        cout << *it << " ";
    }
    return 0;
}

map/set 迭代器底层就是封装红黑树节点,++ 就是走树的中序遍历!


八、迭代器失效问题(高频坑点)

容器修改后,迭代器可能变成“野指针”!

1. vector 失效

插入/删除导致内存重新分配,所有迭代器失效

2. list / map / set 失效

插入不失效删除只有被删节点迭代器失效,其他都有效

// 错误示范:vector 插入后 it 失效
auto it = vec.begin();
vec.insert(it, 100);
// *it 未定义行为!

九、总结:迭代器核心思想

  1. 统一遍历接口:屏蔽 vector/list/map 底层差异
  2. 智能指针:行为像指针,但更安全、更通用
  3. STL 灵魂:算法、容器、迭代器三者协作基础
  4. map/set 迭代器 = 红黑树节点封装,中序遍历输出有序

速记口诀

  • 迭代器 = 智能指针
  • 通用遍历:​​begin()​​ 到 ​​end()​​,​​++it​
  • vector 随机访问,map/set 只能双向
  • 修改容器小心迭代器失效

掌握迭代器,你才算真正入门 STL

需要我给你整理 「迭代器 + 算法 + 容器」三合一实战模板 吗?直接复制就能用在项目和面试里。