范围for循环是c++11起遍历数组最直接安全的方式,自动推导长度,适用于原生数组和标准容器,但数组不可退化为指针;需用int&修改元素,const int&或int用于只读;std::begin/std::end可获取指针迭代器,但不适用于函数参数中的数组。

用范围 for 循环遍历数组(C++11 起)
这是最直接、最安全的方式,编译器自动推导数组长度,无需下标也无需手动计算 sizeof。适用于原生数组和标准容器。
- 必须确保数组不是退化为指针(比如传入函数后),否则
auto&会失效或报错 - 写法:
int arr[] = {1, 2, 3, 4};<br>for (int& x : arr) {<br> x *= 2; // 可修改原数组元素<br>} - 只读场景用
const int&或int(值拷贝),避免意外修改或不必要的复制
用 std::begin / std::end 配合传统 for
当需要访问迭代器位置(比如想跳过前两个元素),又不想暴露下标变量时,这个组合比手算 arr + N 更清晰可靠。
-
std::begin(arr)和std::end(arr)对原生数组返回真正的指针迭代器,类型是int*,不是std::vector::iterator - 注意:不能对函数参数里的数组用,因为形参是
int*,std::begin会失败 - 示例:
for (auto it = std::begin(arr); it != std::end(arr); ++it) {<br> std::cout }
用 std::span(C++20)统一处理“带长度的原始内存”
当你有一块内存(比如从 C API 拿到的 int* 和长度 n),又想享受范围 for 的便利,std::span 是唯一不拷贝、不依赖模板推导的方案。
-
std::span本身不拥有数据,只是视图;构造时需确保原始指针生命周期长于 span - 常见误用:
std::span{arr}在数组是函数局部变量时没问题,但std::span{ptr, len}中的ptr若指向栈临时对象就危险 - 用法:
std::span s{arr};<br>for (int x : s) { /* ... */ }
为什么不能直接用 std::for_each + lambda?
可以,但容易忽略两个关键限制:它无法在循环中提前退出(break),也不能直接修改数组大小(对原生数组无意义,但若误用于 std::vector 容易混淆)。
-
std::for_each(std::begin(arr), std::end(arr), [](int& x) { x++; });是合法的,但调试时难以打断点逐次看执行流程 - 如果逻辑含条件跳出,硬套
std::for_each只能靠异常或外部标志位,反而更难读 - 它本质是算法接口,适合“纯遍历+副作用”,不适合“遍历+控制流”
真正麻烦的从来不是“怎么写”,而是数组上下文是否还保有尺寸信息——传进函数就丢,堆上分配没元数据,C 风格接口只给指针。选哪种方式,先盯住那块内存的来源和生命周期。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











