iterator本质是容器访问代理,安全高效使用需避免类型、时机、更新三类错误;vector和deque支持随机访问(如it+5),list仅支持++/--。

直接说结论:iterator不是“用不用”的问题,而是“怎么安全、高效、不踩坑地用”——它本质是容器的访问代理,用错类型、用错时机、用完不更新,三者任一都会导致未定义行为。
vector 和 deque 的 iterator 支持随机访问,但 list 不行
这是最常被忽略的底层差异。你写 it + 5 或 it[3],在 std::vector 或 std::deque 里合法;但在 std::list 里编译直接报错,因为它的迭代器只支持 ++ 和 --。
-
std::vector<int>::iterator</int>是随机访问迭代器,可做算术运算:it + n、it1 -
std::list<int>::iterator</int>是双向迭代器,只支持++it、--it、it1 == it2 - 误用会导致编译失败(如
list.begin() + 1),或逻辑错误(如用比较两个 <code>list迭代器——结果不可靠)
erase 后必须用返回值更新迭代器,不能 ++it
这是运行时崩溃的高发区。调用 container::erase(it) 后,it 立即失效,再对它执行任何操作(包括 ++it)都是未定义行为。
- 错误写法:
for (auto it = v.begin(); it != v.end(); ++it) { if (*it == 0) v.erase(it); }——erase后it已无效,++it触发崩溃 - 正确写法:
for (auto it = v.begin(); it != v.end(); ) { if (*it == 0) it = v.erase(it); else ++it; } - 注意:
erase返回的是下一个有效位置,不是void;std::list::erase和std::map::erase同样适用该规则
const_iterator 和 iterator 类型不兼容,不能混传
你不能把 container.cbegin() 得到的 const_iterator 传给只接受 iterator 的函数,哪怕容器本身是非 const 的。
- 常见错误:函数签名是
void process(std::vector<int>::iterator it)</int>,却传入v.cbegin()—— 编译失败,提示no known conversion - 解决办法有三:改函数参数为
std::vector<int>::const_iterator</int>,或用模板泛化(template<typename iter></typename>),或确保传入的是v.begin() - 更隐蔽的坑:
auto it = v.cbegin()推导出的是const_iterator,后续若想修改元素(*it = 42)会编译失败
reverse_iterator 的 base() 返回位置有偏移,别直接解引用
std::reverse_iterator 不是“倒着走的普通迭代器”,它内部包装一个正向迭代器,并通过调整语义实现反向遍历——这带来一个关键偏移:rbegin().base() 指向 end(),而不是 last。
- 例如:
std::vector v = {1,2,3}; auto rit = v.rbegin();,此时*rit == 3,但rit.base() == v.end(),不是v.begin() + 2 - 若需转换为正向迭代器并安全使用,要手动减一:
auto it = rit.base(); --it;(前提是rit不等于rend()) - 混用
rbegin()和begin()做算法参数(比如传给std::distance)会触发类型不匹配,必须统一类型
真正难的从来不是“怎么写出来”,而是知道哪一行代码在什么容器、什么上下文、什么并发/修改场景下会悄悄失效。迭代器失效规则因容器而异,vector 扩容全废,list 删一个只废一个,map 插入完全不废——这些细节不记牢,调试时花半天都找不到根因。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











