<p>应使用 arr + size - 1 获取最后一个元素地址进行反向遍历;直接用 arr + 5 越界,解引用危险;推荐 std::span(C++20)配合 rbegin()/rend() 安全遍历。</p>

用 end() - 1 获取最后一个元素地址再递减遍历
数组名本身是首元素地址,但没有内置的“末尾前一个”指针;对原生数组必须手动算出末尾元素地址。假设 int arr[5] = {1,2,3,4,5};,&arr[4] 或 arr + 4 才是合法的最后一个元素地址。直接写 arr + 5 指向的是越界位置(可读但不可解引用),反向遍历时若从那里开始减一,首次解引用就可能出错。
推荐做法:用 arr + size - 1 初始化指针,然后循环递减直到 arr - 1 之前停止:
int arr[5] = {1,2,3,4,5};
int* p = arr + 4; // 指向最后一个元素
while (p >= arr) {
std::cout << *p << " ";
--p;
}用 std::reverse_iterator 避免手算边界
对 std::array 或 std::vector,优先用标准库迭代器,它自动处理反向逻辑,不依赖手动偏移计算。注意:std::array::rbegin() 返回的是 reverse_iterator,不是原生指针,不能直接和 int* 混用。
-
std::array<int> a = {1,2,3,4,5};</int>→for (auto it = a.rbegin(); it != a.rend(); ++it) -
std::vector<int> v = {1,2,3};</int>→ 同样适用rbegin()/rend() - 原生数组无法直接调用
rbegin(),必须先转成std::span(C++20)或封装为std::array视图
反向遍历时访问 *(p-1) 容易越界
常见错误是把循环条件设成 p > arr 却在循环体内写 *(--p),导致最后一次递减后 p == arr,再执行 --p 就变成 arr - 1,解引用即未定义行为。
立即学习“C++免费学习笔记(深入)”;
安全写法只有两种:
- 先解引用,再递减(且条件为
p >= arr) - 用
do-while:先解引用,再判断是否还能继续(适合至少一个元素的场景) - 绝对不要在条件中用
--p或p--做判断依据
C++20 起可用 std::span 统一原生数组与容器的反向遍历
std::span 是轻量视图,能绑定原生数组并提供 rbegin()/rend(),不用复制、不改变所有权:
int arr[5] = {1,2,3,4,5};
std::span s(arr); // 自动推导 size
for (auto it = s.rbegin(); it != s.rend(); ++it) {
std::cout << *it << " "; // 输出 5 4 3 2 1
}注意:如果数组大小未知(比如只传了 int*),std::span 构造会失败,必须显式传入长度 —— 这恰恰说明,反向遍历永远绕不开“知道长度”这个前提。


















