矩阵乘法必须首先检查左矩阵列数等于右矩阵行数,否则应抛出std::invalid_argument异常;使用std::vector时需确保非空且每行长度一致,推荐一维vector模拟二维以提升缓存友好性。

矩阵乘法的维度合法性检查必须放在最前面
两个矩阵能相乘的前提是:左矩阵的列数等于右矩阵的行数。不检查就直接计算,轻则结果全错,重则访问越界崩溃。std::vector 或裸 int** 都不会自动做这个判断,得自己写。
- 假设左矩阵
A是m x k,右矩阵B是k x n,结果C应为m x n - 若
A列数 ≠B行数,应立刻返回错误或抛异常(比如std::invalid_argument) - 用裸数组时,这个信息通常靠传参显式带入,例如:
multiply(A, m, k, B, k, n, C)
用 std::vector<:vector>> 实现更安全但要注意性能陷阱
动态二维 vector 写起来直观,但默认初始化和内存布局可能拖慢乘法——尤其是大矩阵。每行是独立分配的,缓存不友好。
std::vector> multiply(const std::vector>& A, const std::vector>& B) { int m = A.size(), k = A[0].size(); int n = B[0].size(); if (k != (int)B.size()) throw std::invalid_argument("Dimension mismatch"); std::vector> C(m, std::vector(n, 0)); for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) for (int p = 0; p < k; ++p) C[i][j] += A[i][p] * B[p][j]; return C;
}
- 注意:
A[0].size()前要确保A非空且每行长度一致,否则行为未定义 - 三层循环顺序固定为
i→j→p(不是i→p→j),这对现代 CPU 缓存更友好 - 如果矩阵很大,建议改用一维
std::vector模拟二维(行优先),避免指针跳转开销
裸二维数组(栈/堆)需手动管理尺寸,容易越界
用 int A[100][100] 或 int** A 时,编译器不检查 A[i][j] 是否合法。下标错一位,可能读到相邻变量甚至段错误。
立即学习“C++免费学习笔记(深入)”;
- 栈数组如
int A[3][4], B[4][5];可直接用,但尺寸必须编译期确定 - 堆分配
int** A = new int*[m]; for(...) A[i] = new int[k];要配对delete[],否则泄漏 - 推荐用
std::unique_ptr管理:auto A = std::make_unique<:unique_ptr>[]>(m);
常见错误:混淆行列索引或累加逻辑
最容易写错的是内层累加没清零,或者把 A[i][p] * B[p][j] 错写成 A[i][j] * B[i][j]——那根本不是矩阵乘法,而是逐元素乘。
- 结果矩阵
C[i][j]必须初始化为 0,否则含垃圾值 - 中间求和变量不能复用上一轮的残留值(尤其用单个
sum变量时) - 调试时可先用 2×2 小矩阵手算验证:比如
A={{1,2},{3,4}},B={{0,1},{1,0}},结果应为{{2,1},{4,3}}
实际工程中,小矩阵用 vector 足够;高频/大矩阵务必考虑内存连续性、SIMD 指令或 Eigen 等库。手写时,维度检查和索引边界永远比优化循环更重要。