最稳妥的二维向量类实现是封装 std::vector:内部持 std::vector<std::vector<T>> data_,提供 Vec2D(rows, cols, value) 构造函数和 operator()(i,j) 访问,内置边界检查与 RAII。

用 std::vector 嵌套实现二维向量类,别手写内存管理
直接继承 std::vector<:vector>></:vector> 或封装它,是最稳妥的起点。手写二维数组 + new/delete 容易漏掉拷贝构造、赋值重载、移动语义,一跑多线程或传参就崩。用标准容器,size()、边界检查、RAII 都白送。
典型结构是:一个 class Vec2D 内部持有一个 std::vector<:vector>></:vector> 成员,构造时按行数列数初始化,不暴露裸指针。
- 初始化时用
vec2d(rows, cols, value = 0.0)构造函数,调用data_.resize(rows, std::vector<double>(cols, value))</double> - 访问元素统一走
operator()(int i, int j)(非operator[]),便于加越界断言:assert(i >= 0 && i = 0 && j - 禁止提供
data()返回裸指针——否则用户可能误存地址,后续 resize 后悬垂
operator+ 和 operator- 必须返回新对象,不能修改原对象
这是值语义的基本要求。如果在 operator+ 里直接改 *this,那 a + b 就会悄悄改掉 a,反直觉且破坏表达式可组合性(比如 (a + b) + c 中第一个加法副作用会影响第二个)。
- 两个操作符都声明为
const成员函数,参数也用const Vec2D& - 函数体内先创建等尺寸结果对象:
Vec2D res(rows(), cols()),再双层循环赋值:res(i, j) = (*this)(i, j) + other(i, j) - 不要试图返回
*this引用——语法不允许,编译直接报错:invalid initialization of non-const reference
行列不匹配时加运行时检查,别靠编译期硬编码
二维向量加减法数学上要求维度严格一致。如果只在文档里写“请确保行列相同”,实际用的时候遇到 Vec2D a(3,4), b(3,5); auto c = a + b; 就会静默出错(比如只算前 4 列,后 1 列未定义)。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
- 在
operator+/operator-开头立刻校验:if (rows() != other.rows() || cols() != other.cols()) throw std::invalid_argument("dimension mismatch"); - 不用
static_assert——行列数是运行时决定的,编译期根本不知道 - 错误信息里明确写出期望和实际尺寸,比如
"expected 3x4, got 3x5",方便调试定位
性能敏感场景下避免重复构造临时对象
连续做多个运算如 a + b + c + d,默认实现会生成 3 个临时 Vec2D 对象,每步都分配内存。对小矩阵不明显,但若单个矩阵有上万元素,开销就实打实了。
短期解法是加一个「就地加法」成员函数:void add_inplace(const Vec2D& other),内部直接改 data_,不 new 新对象。调用方权衡:要表达清晰用 +,要性能且确定生命周期可控,就用 add_inplace。
-
add_inplace同样要做维度检查,且声明为void,不返回*this(避免链式调用掩盖副作用) - 别为了省一次分配而把
operator+=实现成调用add_inplace——这违反了「+=应该返回*this&」的惯例,会让(a += b) += c这种写法失效 - 真要极致优化,再考虑表达式模板,但那已超出“简单类”范畴,容易引入隐晦 bug
operator() + 断言,后者靠命名区分(+ vs add_inplace),比堆砌模板技巧管用得多。

















