递归遍历数组不能直接传 int[],因数组名退化为指针导致长度信息丢失,必须显式传长度或用 std::vector;二维数组需固定一维递归另一维或展平处理;普通线性遍历推荐循环而非递归。

递归遍历数组时,为什么不能直接传 int[]?
因为 C++ 中数组名作为函数参数会退化为指针,sizeof 失效,无法在递归函数内得知数组长度。你传 int arr[] 进去,实际拿到的是 int*,没有尺寸信息 —— 递归根本不知道“什么时候停”。
常见错误现象:Segmentation fault 或无限递归,尤其当忘记控制终止条件或误判边界时。
- 必须显式传入长度(如
size_t n)或使用容器封装(如std::vector) - 推荐用索引而非指针偏移做递归变量:更直观、不易越界(比如用
index从0到n-1) - 终止条件必须严格写成
if (index >= n),而不是==—— 若初始调用传错n,==会跳过检查直接崩溃
用 std::vector 写递归遍历更安全吗?
是的,但不是因为“自动知道大小”——而是它把大小和数据绑定了,且支持 .size() 和 .at() 边界检查(调试模式下抛 std::out_of_range)。不过注意:递归本身不改变安全性,关键是你怎么用。
实操建议:
- 传
const std::vector<int>& vec</int>,避免拷贝;递归函数签名类似void traverse(const std::vector<int>& v, size_t i)</int> - 用
v.at(i)替代v[i],能在越界时暴露问题,而不是静默读垃圾内存 - 如果只是读取,递归深度大时要考虑栈溢出风险(
vector本身不缓解这点)
递归遍历二维数组(如 int arr[3][4])怎么写?
二维数组本质是连续内存,可以展平处理。但直接递归按行/列拆分更符合直觉,也便于扩展逻辑(比如只处理某一行)。
典型做法是固定一维,递归另一维:
- 若按行优先遍历:外层循环行号,每行内递归列索引(或反过来)
- 若想纯递归无循环:把二维映射为一维索引,用
row * cols + col计算位置,总长 =rows * cols - 注意:
int arr[M][N]传参必须写明第二维(如void f(int arr[][4], int rows)),否则编译失败
递归 vs 循环:什么情况下非用递归不可?
其实遍历线性数组几乎不需要递归——循环更高效、无栈溢出风险、可读性更好。递归真正有用的地方是结构天然递归的场景,比如树、图、嵌套容器(vector<vector>></vector>)、或需要回溯的路径搜索。
如果你只是想“练递归”,那没问题;但线上代码中,对普通一维数组硬套递归,容易被 review 打回来:
- 每次函数调用有压栈开销,
O(n)空间复杂度,而循环是O(1) - 编译器很难对递归做尾调用优化(除非写成严格尾递归且开启
-O2,但数组遍历难满足) - 调试时栈帧多,不如单层循环一眼看清状态
真正该警惕的,是把递归当语法糖用,却忽略了它带来的隐式资源消耗和边界脆弱性。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











