反向迭代器应使用容器的rbegin()和rend(),它们返回reverse_iterator类型;rbegin()指向末元素,rend()指向首元素前位置,不可解引用;base()返回对应正向迭代器但偏移一位。

反向迭代器怎么写,rbegin() 和 rend() 是啥
直接用容器自带的 rbegin() 和 rend() 就行,它们返回的是 reverse_iterator 类型,不是普通指针或 iterator。别试图用 --it 从 end() 开始倒着走——那不是标准做法,容易越界且语义不清。
常见错误现象:for (auto it = vec.end(); it != vec.begin(); --it) 看似能跑,但 it-- 在 vec.end() 上解引用是未定义行为;而且 it != vec.begin() 会漏掉第一个元素(因为停在 begin() 而不进去)。
-
rbegin()指向最后一个元素,rend()指向“第一个元素前的位置”,和正向的begin()/end()对称 - 所有标准序列容器(
vector、deque、list)都支持,array也支持;但forward_list不支持反向迭代(没rbegin()) - 反向迭代器解引用后得到的值,和对应正向位置的值完全一致,只是遍历方向相反
reverse_iterator 的 base() 干嘛用的
它用来拿到底层对应的正向迭代器。注意:不是简单映射,rit.base() 返回的迭代器比 rit 当前指向位置「往前一位」。比如 rit == c.rbegin() 时,rit.base() == c.end();rit == c.rend() 时,rit.base() == c.begin()。
这坑很多人踩:想把反向迭代器转成正向位置做下标计算,直接写 rit.base() - c.begin() 会多算 1。正确方式是 (rit.base() - c.begin()) - 1,或者更安全地用 std::distance(c.begin(), rit.base()) - 1。
立即学习“C++免费学习笔记(深入)”;
- 只在需要混合正向/反向逻辑时才调
base(),比如在反向遍历中调用一个只接受正向迭代器的算法 -
base()返回的是 const 或非 const 版本,取决于反向迭代器类型,不能跨 const 性质赋值 - 对
rend()调base()是合法的,结果是begin();但对rend()解引用是未定义行为
自定义容器怎么加反向迭代器支持
核心是提供 rbegin() 和 rend() 成员函数,返回你封装的 reverse_iterator<T> 类型。标准库的 std::reverse_iterator 可以复用,只要你的正向迭代器满足 LegacyIterator 要求(有 operator++、operator*、operator!= 等)。
常见错误现象:自己手写 reverse_iterator 类,但 operator* 返回了临时对象的引用,导致悬垂引用;或者 operator++ 实现成向前走,实际该向后走(反向迭代器的 ++ 应该让底层正向迭代器 --)。
- 推荐用
std::reverse_iterator<your_iterator>包装,而不是重造轮子 -
rbegin()应返回reverse_iterator(end()),rend()返回reverse_iterator(begin()) - 如果容器支持
const迭代,必须同时提供crbegin()/crend(),否则在 const 容器上调用rbegin()会编译失败
反向遍历性能有影响吗
对 vector 和 deque,没有额外开销:反向迭代器本质就是对正向迭代器的封装,++ 编译后等价于 --,* 直接取址。但对 list,虽然单次操作仍是 O(1),但 CPU 缓存局部性变差——正向遍历时节点大概率在内存中连续分布,反向则跳来跳去。
真正要注意的是:别在循环里反复调 container.rbegin()。有些同学写 for (auto it = c.rbegin(); it != c.rend(); ++it) 是 OK 的,但若写成 for (auto it = c.rbegin(); it != c.rend(); ++it, c.rbegin())(误加),每次都在重建迭代器,可能触发冗余计算(尤其自定义容器没内联时)。
-
vector::rbegin()是O(1)且通常被内联,放心用 - 避免在反向循环体里修改容器大小(如
push_back()或erase()),这会让rend()失效,引发未定义行为 - 如果只是要倒序访问索引,
for (size_t i = v.size(); i-- > 0; )比反向迭代器更快(无迭代器对象构造/析构),但可读性差,且不通用
事情说清了就结束。最常被忽略的是 rend() 的语义——它不是指向第一个元素,而是“第一个元素之前”,所以不能解引用;还有就是 base() 的偏移关系,一不留神就差 1。


















