自定义Matrix类拷贝构造及赋值运算符拷贝不全问题
自定义Matrix类拷贝构造/赋值仅部分数据拷贝问题排查与修复
问题现象
自定义Matrix类基础功能正常,但通过拷贝构造函数或赋值运算符基于已有矩阵创建新矩阵时,仅部分数据被拷贝。该类内部通过一维double数组指针存储矩阵数据,通过getIndex函数计算二维坐标对应的一维数组索引。
测试代码
Matrix m(3,10); for(int i = 0; i<m.getColumns(); i++){ m.set(0,i, 4); } Matrix l(m); Matrix c = m; cout << m << endl; cout << l << endl; cout << c << endl;
测试输出
4 4 4 4 4 4 4 4 4 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
类代码实现
Matrix.h
#pragma once #include <iostream> using namespace std; class Matrix { private: int r; int c; int getIndex(int r, int c) const; double* matrix; public: Matrix(int nRows, int nColumns); explicit Matrix(int nRows); Matrix(const Matrix &); ~Matrix(); double get(int row, int col) const; void set(int row, int col, double value); int getRows() const; int getColumns() const; friend ostream& operator<<(ostream& os, const Matrix& m); Matrix& operator=(Matrix rhs); };
Matrix.cpp
#include <Matrix.h> #include <cassert> #include <iostream> #include <utility> using namespace std; Matrix::Matrix(int nRows, int mColumns) { assert(nRows>0 && mColumns>0); r = nRows; c = mColumns; matrix = new double[r*c]{}; //fills with zeros for(int i = 0; i<r*c; i++){ matrix[i] = 0; } } Matrix::Matrix(int nRows) { assert(nRows>0); r = nRows; c = nRows; matrix = new double[r*c]{}; for(int i = 0; i<r*c; i++){ matrix[i] = 0; } //Makes the identity matrix for(int i = 0; i<r; i++){ set(i,i, 1); } } Matrix::Matrix(const Matrix& other){ r = other.getRows(); c = other.getColumns(); matrix = new double[r*c]; *matrix = *other.matrix; } int Matrix::getIndex(int row, int col) const { int index = row*c; index += col; return index; } int Matrix::getRows() const { return r; } int Matrix::getColumns() const { return c; } void Matrix::set(int row, int col, double value){ matrix[getIndex(row, col)] = value; } double Matrix::get(int row, int col) const{ return matrix[getIndex(row,col)]; } Matrix::~Matrix() { } ostream& operator<<(ostream& os, const Matrix& m){ for(int i = 0; i<m.getRows(); i++){ for(int j = 0; j<m.getColumns(); j++){ os << m.get(i,j); os << ' '; } os << '\n'; } os << endl; return os; } Matrix& Matrix::operator=(Matrix rhs){ r = rhs.r; c = rhs.c; swap(matrix, rhs.matrix); return *this; }
问题根源与修复方案
核心问题
- 拷贝构造函数只拷贝单个元素:
*matrix = *other.matrix;仅拷贝了数组的第一个元素,未遍历整个数组完成所有元素的拷贝,导致新矩阵只有第一个元素与原矩阵一致。 - 析构函数未释放内存:空实现的析构函数没有释放
matrix指向的堆内存,会引发内存泄漏问题。 - 赋值运算符依赖错误的拷贝构造:赋值运算符采用传值方式接收参数,而参数
rhs是通过错误的拷贝构造函数创建的,因此赋值后的矩阵自然也只有部分数据正确。
修复代码
1. 修正拷贝构造函数
将单个元素拷贝改为遍历整个数组拷贝所有元素,或使用std::copy简化实现:
Matrix::Matrix(const Matrix& other){ r = other.r; c = other.c; matrix = new double[r*c]; // 方式1:遍历拷贝 for(int i = 0; i < r*c; ++i){ matrix[i] = other.matrix[i]; } // 方式2:使用std::copy(需包含<algorithm>头文件) // std::copy(other.matrix, other.matrix + r*c, matrix); }
2. 完善析构函数
添加堆内存释放逻辑,注意用delete[]释放数组:
Matrix::~Matrix() { delete[] matrix; }
3. 简化构造函数(可选优化)
构造函数中new double[r*c]{};已经完成了数组的零初始化,无需额外循环赋值0,可删除冗余代码:
Matrix::Matrix(int nRows, int mColumns) { assert(nRows>0 && mColumns>0); r = nRows; c = mColumns; matrix = new double[r*c]{}; // 已自动初始化所有元素为0 }
修复后效果
修正后再次运行测试代码,拷贝得到的矩阵l和c会与原矩阵m完全一致,输出所有第一行元素为4,其余为0。
内容的提问来源于stack exchange,提问作者Herman Neple
相关产品推荐
相关产品推荐

