矩阵加减必须封装为类并重载operator+和operator-,使用std::vector一维存储+行列信息,检查维度匹配,返回新对象,三个const缺一不可,索引按i*cols+j计算。

矩阵加减必须重载 operator+ 和 operator-
不能靠裸指针或原始二维数组直接运算,C++ 不支持对数组类型自动重载运算符。必须封装成类(如 Matrix),把数据存为 std::vector<:vector>> 或一维 std::vector + 行列信息,再在类内定义成员函数形式的运算符重载。
常见错误是试图对 double a[3][3] 重载 + —— 编译器直接报错:error: cannot overload 'operator+' for type 'double [3][3]'。
- 推荐用一维存储(
std::vector)+data rows/cols成员,内存连续、缓存友好、避免 vector of vector 的指针跳转开销 - 运算符应返回新对象(非引用),避免返回局部对象引用或悬垂引用
- 必须检查维度匹配:加减要求左右操作数
rows和cols完全相等,否则抛std::invalid_argument
重载函数签名要写成 const 成员 + const 引用参数
典型写法是:Matrix operator+(const Matrix& other) const。三个 const 各有作用:
- 参数
const Matrix&:避免拷贝,且禁止修改传入矩阵 - 函数末尾
const:保证不修改当前对象(*this)状态,才能被 const 对象调用 - 返回值不加
const:允许链式调用(如a + b + c),C++11 后移动语义也能生效
如果漏掉任意一个 const,可能触发隐式拷贝、编译失败,或导致 const 对象无法参与运算(例如临时对象、const 局部变量)。
立即学习“C++免费学习笔记(深入)”;
一维存储下加减运算的索引计算别写错
假设按行优先存储,元素 (i, j) 对应一维下标是 i * cols + j。加减时必须用这个公式遍历,而不是嵌套 [i][j](那是一维 vector 存 vector 才有的语法)。
错误示例(误当二维访问):
data[i][j] += other.data[i][j]; // 编译不过:data 是 vector,不支持 [][][]
正确写法(一维索引):
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < cols; ++j) {
size_t idx = i * cols + j;
result.data[idx] = data[idx] + other.data[idx];
}
}
- 循环用
size_t(无符号),避免与int混合比较引发警告 - 不要手写
data[i * cols + j]多次——提取成变量或用 lambda 封装可读性更好 - 若矩阵很大,可考虑 OpenMP 并行化外层循环,但小矩阵反而因开销得不偿失
构造函数和拷贝控制要同步更新
一旦用了动态存储(std::vector),默认拷贝构造和赋值已足够安全,无需手动写(遵循 Rule of Zero)。但如果自行管理裸指针(如 double* data),就必须显式定义拷贝构造、拷贝赋值、移动构造、析构函数(Rule of Five),否则加减后对象析构会 double-free。
实际项目中强烈建议:用 std::vector,禁用裸 new/delete;所有资源管理交给标准库。
容易被忽略的一点:如果类里加了 operator+= / operator-=,它们应返回 *this(Matrix&),且必须是 non-const 成员函数——否则无法用于 a += b 这种左值场景。








