rbegin()和rend()提供反向遍历,rbegin()指向末元素,rend()指向首元素前位置,是反向哨兵不可解引用,循环须用!=而非==判断终止。

用 rbegin() 和 rend() 遍历容器最直接
几乎所有标准容器(vector、list、deque、map 等)都提供 rbegin() 和 rend() 成员函数,返回反向迭代器。它们不是“从 end 往前走”,而是逻辑上把容器倒过来看待: rbegin() 指向最后一个元素,rend() 指向第一个元素的前一个位置(即“反向末尾”)。
常见错误是误以为 rend() 对应原容器的 begin() —— 实际上它等价于 reverse_iterator(begin()),语义上是反向遍历的结束哨兵,不能解引用。
- 必须用
!=判断循环终止,不能用或 <code>(反向迭代器不支持随机比较) - 遍历时用
++it向前移动(逻辑上是“往更小索引走”),不是--it - 对
vector这类连续内存容器,反向迭代性能几乎无损耗;但对list,++仍需跳指针,和正向一样
vector<int> v = {1, 2, 3, 4};
for (auto it = v.rbegin(); it != v.rend(); ++it) {
cout << *it << " "; // 输出:4 3 2 1
}手动构造 reverse_iterator 要小心 base() 偏移
当你需要从普通迭代器出发构建反向迭代器时(比如传入某函数要求 reverse_iterator),得用 reverse_iterator<It>(it) 构造。但注意:reverse_iterator(it) 对应的逻辑位置,其实是 it - 1。
这是因为 reverse_iterator::base() 返回的是“对应正向位置”,且满足恒等式:(reverse_iterator(it)).base() == it,而该构造本身会自动后退一步以对齐语义。容易踩坑的地方是:拿 end() 构造 rbegin() 是对的,但拿 begin() 构造出来的不是 rend() —— 它对应的是 begin() - 1,越界。
立即学习“C++免费学习笔记(深入)”;
- 正确配对:
reverse_iterator(v.end())等价于v.rbegin();reverse_iterator(v.begin())等价于v.rend() - 不要对
begin()调用base()后再解引用——那指向非法地址 - 如果容器为空,
v.rbegin() == v.rend(),此时任何解引用都未定义行为
std::reverse 不是迭代器,别混淆用途
std::reverse 是算法,作用是原地翻转容器内容,不是生成反向视图。有人看到名字就以为它能“让迭代变反向”,结果调用后数据顺序真被改了,后续逻辑全乱。
它和反向迭代器完全无关:一个改数据,一个改访问顺序。如果你只需要读取逆序,绝对不要碰 std::reverse;只有当你明确要永久反转容器内容时才用它。
-
std::reverse(v.begin(), v.end())后,再用正向迭代器遍历就是逆序效果,但代价是修改原容器 - 对
map、set这类有序关联容器,std::reverse无效(不支持随机访问迭代器) - 若只是临时逆序处理,优先选
rbegin()/rend()—— 零拷贝、零修改、语义清晰
自定义容器实现 rbegin() 的关键点
如果你写自己的容器并希望支持反向遍历,必须提供 rbegin() / rend(),且返回类型为 std::reverse_iterator<iterator> 或等价类型。核心约束只有一个:保证 rbegin() 解引用得到最后一个元素,rend() 解引用非法,且 ++rbegin() 能到达倒数第二个元素。
最容易漏掉的是 const 版本:必须同时提供 crbegin() / crend()(C++14 起),否则 const 容器无法用范围 for 逆序遍历。
- 返回
reverse_iterator(end())实现rbegin(),返回reverse_iterator(begin())实现rend() - 确保
reverse_iterator的operator++内部调用底层迭代器的--(这是标准要求) - 如果底层迭代器不支持
--(如单向链表的前向迭代器),你的容器就不能提供反向迭代器 —— 这是语言限制,不是实现不到位
反向迭代器的“反向”是逻辑视图,不是物理移动方向;真正容易出错的,是把 base() 当成可安全解引用的位置,或者在空容器上没做判空就直接取 rbegin()。











