You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义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;
}

问题根源与修复方案

核心问题

  1. 拷贝构造函数只拷贝单个元素:*matrix = *other.matrix;仅拷贝了数组的第一个元素,未遍历整个数组完成所有元素的拷贝,导致新矩阵只有第一个元素与原矩阵一致。
  2. 析构函数未释放内存:空实现的析构函数没有释放matrix指向的堆内存,会引发内存泄漏问题。
  3. 赋值运算符依赖错误的拷贝构造:赋值运算符采用传值方式接收参数,而参数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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 07:25:22