主对角线元素可通过for循环遍历:for(int i = 0; i < Math.min(rows, cols); i++)访问ai。常见错误是误用赋值号或越界,应确保i在行列最小值范围内。

如何用 for 循环遍历主对角线元素
主对角线指行索引和列索引相等的位置(即 i == j),前提是二维数组为方阵。如果不是方阵,主对角线长度由 min(行数, 列数) 决定。
常见错误是直接写 for (int i = 0; i 却没检查 <code>n 是否超出列边界——比如 int arr[5][3] 中,i=3 时访问 arr[3][3] 就越界了。
- 先获取行数
rows和列数cols,取较小值作为循环上限 - 若用
std::vector<:vector>></:vector>,优先用.size()而非硬编码 - 对于 C 风格数组,需手动传入维度,不能依赖
sizeof(arr)/sizeof(arr[0])获取列数(该表达式只给出首行地址大小)
副对角线求和要注意索引映射关系
副对角线满足 i + j == n - 1,其中 n 是有效对角线长度(仍取 min(rows, cols))。但注意:这个公式仅在“从左上到右下”为标准主对角线的前提下成立;如果数组不是方阵,副对角线可能不连续或无法完整存在。
例如 int arr[4][2],行数 4、列数 2,有效 n = 2,那么副对角线只包含 arr[0][1] 和 arr[1][0] —— 这两个位置确实满足 i + j == 1(因为 n-1 == 1)。
立即学习“C++免费学习笔记(深入)”;
- 不要盲目用
arr[i][n-1-i],必须确保n-1-i在[0, cols)范围内 - 更安全的写法是:对每个
i,计算j = n - 1 - i,再判断j >= 0 && j - 如果只要求「正方形二维数组」的副对角线,可省略范围检查,但代码复用性会下降
用 std::accumulate 处理 vector 时别忽略嵌套结构
std::accumulate 本身不支持直接展开二维容器,试图写 accumulate(mat.begin(), mat.end(), 0) 会导致编译失败:因为迭代器解引用得到的是 std::vector<int></int>,不能直接加到 int 上。
正确做法是外层循环 + 内层 accumulate,或用嵌套 lambda。例如主对角线:
int sum = 0;
int n = std::min(mat.size(), mat.empty() ? 0 : mat[0].size());
for (int i = 0; i < n; ++i) {
sum += mat[i][i];
}
- 空
vector必须判空,否则mat[0].size()触发未定义行为 - 若坚持函数式风格,可用
std::inner_product配合自定义二元操作,但可读性通常不如显式循环 - 性能上无本质差异,现代编译器对简单循环优化很好,不必强求 STL 算法
遇到 segmentation fault 先查数组存储方式
C++ 中二维数组未必是连续内存块。比如 int** arr 指向一组分别 new 出来的行,此时 arr[i][j] 是两次解引用,任意一行为空或越界都会崩;而 int arr[10][10] 或 std::array<:array>, 10></:array> 是一块连续内存,访问更可控。
- 调试时用
gdb查看崩溃地址,配合info registers和x/10wx $rdx(示例)观察指针是否为nullptr或非法值 - 用
valgrind --tool=memcheck可快速定位越界读写 - 如果函数参数是
int arr[][N],必须把列数N作为模板参数或宏传入,否则形参退化为int*,失去二维语义
实际写的时候,多数情况只需一个带边界检查的 for 循环。真正容易出问题的不是算法逻辑,而是对非方阵、空容器、动态分配内存这些边缘情形的疏忽。


















