【问题标题】:Matrix Class Mem Allocating & Overloading矩阵类内存分配和重载
【发布时间】:2025-12-01 16:45:01
【问题描述】:

我想在构造函数中为矩阵动态分配内存。我希望 mData 成为指向 double 值的指针。

getvalue() setValue()getter应该返回row_x和column_x的值,setter应该设置row_x和column_x的值,但是getter和setter好像不起作用;

operator + 必须检查 2 个相同大小的矩阵,并逐个元素求和。

Operator * 还需要检查 2 个相同大小的矩阵,并逐个元素相乘。

Operator ^ 需要检查是否可以将行乘以第 2 列矩阵,然后执行此操作。

这是我的代码:

class Mat {
private:
    uint16_t mRows;
    uint16_t mCols;
    double * mData;
public:
    Mat(uint16_t r, uint16_t c){
        mRows = r;
        mCols = c;
        mData = new double[mRows * mCols];
    }
    Mat(uint16_t c){
        mCols = c;
        mRows = 1;
        mData = new double [mCols];
    }
    Mat(){
        mRows = 0;
        mCols = 0;
    }
    Mat(const Mat &mat) : mRows(mat.mRows), mCols(mat.mCols), mData(mat.mData){

    }
    double getValue(uint16_t r, uint16_t c){

        double val = mData [r*c + c];
        return val;
    }
    void setValue(uint16_t r, uint16_t c,double value){
        mData[r*c + c] = value;
    }
    ~Mat(){
        
    }
    Mat operator + (const Mat &mat){
        Mat result;
        int ok=0;
        if(mat.mRows == mRows && mat.mCols == mCols){
            ok=1;
            result.mData[mRows*mCols ] = mData[mRows*mCols ] + mat.mData[mat.mRows*mat.mCols];
        }
        if(ok == 0)
           return result.mData[0];
        else
            return result;
    }
    Mat operator * (const Mat &mat){
        Mat result;
        int ok=0;
        if(mat.mRows == mRows && mat.mCols == mCols){
            ok=1;
            result.mData[mRows*mCols] = mData[mRows*mCols] * mat.mData[mat.mRows*mat.mCols];
        }
        if(ok == 0)
            return result.mData[0];
        else
            return result.mData[mRows*mCols];
    }
     Mat operator ^ (const Mat &mat){
        Mat result;
        int ok=0;
        if(mat.mRows == mCols && mat.mCols == mRows){
            ok=1;
            result.mData[mRows] = mData[mRows] * mat.mData[mat.mCols];
        }
        if(ok == 0)
            return result.mData[0];
        else
            return result.mData[mRows];
    }


};

我想继续这个想法,但我不确定我错过了什么

【问题讨论】:

  • 注意应该是mData[r*mCols+c]而不是r*c+c
  • @MarcStevens 谢谢,现在 getter 和 setter 工作得很好。但是我怎样才能正确完成运算符 + * 和 ^ ?提前致谢。
  • 您可以通过将 mData 更改为 std::vector 来简化您自己的内存管理。然后运算符 +、*、^ 可以简单地遍历向量元素:for (size_t i = 0; i < result.mData.size(); ++i) result.mData[i] = src1.mData[i] + src2.mData[i];。我们可以将第一行和列的双循环简化为所有元素的单循环,因为所有矩阵元素在内存中都是连续的。
  • 不清楚你想用运算符 ^ 做什么,你的意思是常规矩阵矩阵乘法,其中 m x n 矩阵乘以 n x k 矩阵并产生 m x k 矩阵?而不是简单的元素明智。

标签: c++ class matrix heap-memory


【解决方案1】:

你的内存管理坏了。

在您的复制构造函数中,您必须复制mData 的内容,而不仅仅是指针。所以你需要分配一个新的缓冲区并将输入数据复制到那里。

你的析构函数需要删除mData,你正在泄漏内存。

在您的运算符中,您不能使用 默认构造的 矩阵作为目标。您必须创建具有正确尺寸的目标,否则它没有分配缓冲区!

您的运算符的返回值是非法的。您必须始终返回签名中指定的类型。你不能返回result.mData[0],即使是在错误的情况下!在这种情况下,您可以返回默认构造的 Matthrow 异常。

【讨论】:

    【解决方案2】:

    使用std::vector<double> 而不是double* 可以显着简化内存管理和复制操作,并且更不容易出错。 我还注意到元素明智访问中的一个错误,应该使用r*mCols+c 而不是r*c+c。要解决元素矩阵运算的问题,您需要遍历所有元素:

    for (size_t r = 0; r < mRows; ++r)
       for (size_t c = 0; c < mCols; ++c)
          result[r*mCols+c] = src1[r*mCols+c] + src2[r*mCols+c]
    

    这是 Mat 的示例实现。到目前为止,我只完成了operator+,但应该很容易扩展到其他运营商:

    class Mat
    {
    private:
        size_t mRows;
        size_t mCols;
        std::vector<double> mData;
    public:
        // constructors
        Mat(size_t rows, size_t cols, double v = 0.0f)
            : mRows(rows), mCols(cols), mData(mRows*mCols, v)
        {}
        Mat(size_t cols, double v = 0.0f)
            : mRows(1), mCols(cols), mData(mRows*mCols,v)
        {}
        Mat()
            : mRows(0), mCols(0), mData()
        {} 
    
        // automatic copy & move construction just works^TM using std::vector
        Mat(const Mat&) = default;
        Mat(Mat&&) = default;
        // same with automatic copy & move assignment
        Mat& operator= (const Mat&) = default;
        Mat& operator= (Mat&&) = default;
    
        // element access
        double getValue(size_t r, size_t c) const
        {
            return mData[r*mCols + c];
        }
        void setValue(size_t r, size_t c, double value)
        {
            mData[r*mCols + c] = value;
        }
    
        // element access through operator():
        // Mat m(3,3); m(1,2)=5.0f;
        double& operator()(size_t r, size_t c)
        {
            return mData[r*mCols + c];
        }
        const double& operator()(size_t r, size_t c) const
        {
            return mData[r*mCols + c];
        }
    
        // in place addition saves unnecessary memory allocation & copying
        Mat& operator += (const Mat& m)
        {
            if (m.mRows != mRows || m.mCols != mCols)
                throw std::runtime_error("Mat: dimensions don't match");
            // since all matrix elements are contiguous in memory, we can simply to a single for loop
            for (size_t i = 0; i < mData.size(); ++i)
                mData[i] += m.mData[i];
            return *this;
        }
    
        
        Mat operator + (const Mat& m) const
        {
            if (m.mRows != mRows || m.mCols != mCols)
                throw std::runtime_error("Mat: dimensions don't match");
            // copy this Mat into a new Mat
            Mat result(*this);
            // add m to result in place and return result
            result += m;
            return result;
        }
    };
    

    【讨论】: