在 C++ 中添加矩阵

Addition of Matrix in C++

提问人:BS e-Learning 提问时间:3/29/2022 更新时间:3/29/2022 访问量:192

问:

以下代码给了我错误的输出。实际上,它不是在做求和,它实际上是将第二个对象复制到 M3 对象,而不是计算求和。我想我在 + 运算符重载中有一些逻辑错误。有人有什么想法或任何其他建议吗?它显示实际在复制构造函数 cout<data[r][c]<<“\t”; 中调用的输出。但是当我使用 M3.displayData() 时它没有显示输出。 #include

#include <string.h>
using namespace std;

class Matrix{
    private:
        int noOfRows;
        int noOfColumns;
        int **data;
    public:
        Matrix(int noOfRows, int noOfColumns);
        void displayData();
        ~Matrix();
        Matrix (const Matrix &ref);
        Matrix operator + (Matrix m);
        Matrix& operator=(Matrix m) { 
        std::swap(m.noOfRows, noOfRows); 
        std::swap(m.noOfColumns, noOfColumns); 
        std::swap(m.data, data); 
        return *this; }
};

Matrix::Matrix(int inr=0, int inc=0){
    noOfRows=inr; noOfColumns=inc;
    data=new int*[noOfColumns];
    for(int i=0;i<noOfRows;i++)
        data[i]=new int[noOfColumns];
    int d;
    for(int r=0;r<noOfRows;r++){
        for(int c=0;c<noOfColumns;c++){
            cout<<"Enter ...";cin>>d;
            data[r][c]=d;
        }
        cout<<endl;
    }
}

Matrix::Matrix (const Matrix &ref){
    this->data=new int*[ref.noOfColumns];
    for(int i=0;i<ref.noOfRows;i++)
        this->data[i]=new int[ref.noOfRows];
    
    for(int r=0;r<ref.noOfRows;r++){
        for(int c=0;c<ref.noOfColumns;c++){
            this->data[r][c]=ref.data[r][c];
            cout<<this->data[r][c]<<"\t";
        }
        cout<<endl;
    }
}

Matrix Matrix::operator + (Matrix m){
    Matrix ms(m.noOfRows,m.noOfColumns);
    ms=0;
    for (int i=0; i<m.noOfRows; i++) 
        for (int j=0; j<m.noOfColumns; j++){
        ms.data[i][j] = data[i][j]+m.data[i][j];
        return ms;
        } 
    }

void Matrix::displayData(){
    for(int r=0;r<noOfRows;r++){
        for(int c=0;c<noOfColumns;c++)
            cout<<data[r][c]<<"\t";
        cout<<endl;
    }
}

Matrix::~Matrix(){
    delete[] data;
}

int main(){
    Matrix M1(2,2),M2(2,2);
    cout<<"\n Matrix A="<<endl;
    M1.displayData();
    cout<<"\n Matrix B="<<endl;
    M2.displayData();
    cout<<"\n Sum of Matrix="<<endl;
    Matrix M3=M1+M2;
    M3.displayData();
    return 0;
}

Program output is here:

C++ OOP 重载 复制构造函数 赋值运算符

评论

0赞 ChrisMM 3/29/2022
在循环中返回矩阵,而不是在函数末尾返回矩阵。
0赞 paddy 3/29/2022
复制构造函数不会初始化矩阵大小。由于您是按值传递运算符(而不是按引用传递的正确方式),因此这会导致未定义的行为。你的分配也被打破了。仔细检查您分配的维度。使用调试器。Matrix
0赞 PaulMcKenzie 3/29/2022
在使用 .这是先决条件。std::swap
0赞 pale_rider 3/29/2022
为什么在实现赋值运算符时使用赋值?std::swap
2赞 PaulMcKenzie 3/29/2022
@pale_rider -- 使用是完全有效的。赋值运算符没有错。这是复制/交换的成语。问题是复制构造函数已损坏,并且工作复制构造函数是复制/交换工作的必要条件。std::swap

答:

0赞 PaulMcKenzie 3/29/2022 #1

代码至少存在四个问题:

  1. 复制构造函数无法复制 和 值。MatrixnoOfRowsnoOfColumns

  2. 错误地分配了行指针,方法是使用 as 行数。noOfColumns

  3. 在 中,您正在返回循环内部,而您应该在循环完成后返回它。Matrix operator +Matrixfor

  4. 析构函数无法处理所有行和列数据。delete[]

要解决前两个问题,由于默认构造函数和复制构造函数之间有很多通用代码,因此可以创建一个成员函数来分配内存:MatrixAllocate

class Matrix
{
    private:
       void Allocate();
    //... other members
    public:
        Matrix operator + (const Matrix& m);
    // other members...
};

Matrix::Matrix(int inr=0, int inc=0) : noOfRows(inr), noOfColumns(inc)
{
    Allocate();
    // Input code removed...
}

Matrix::Matrix (const Matrix &ref) : noOfRows(ref.noOfRows), noOfColumns(ref.noOfColumns)
{
    Allocate();
    for(int r=0; r < ref.noOfRows; r++)
    {
        for(int c=0; c < ref.noOfColumns; c++)
            data[r][c] = ref.data[r][c];
    }
}

void Matrix::Allocate()
{
    data=new int*[noOfRows];
    for(int i=0;i < noOfRows; i++)
        data[i]=new int[noOfColumns]();
}

对于 ,您应该传递 by const 引用,而不是 by 值(这是对修复过早返回的错误之外的):operator +MatrixMatrix

Matrix Matrix::operator + (const Matrix& m)
{
    Matrix ms(m.noOfRows,m.noOfColumns);
    for (int i=0; i<m.noOfRows; i++) 
    { 
        for (int j=0; j<m.noOfColumns; j++)
            ms.data[i][j] = data[i][j]+m.data[i][j];
    }
    return ms;
}

最后一个问题(析构函数)仅删除行指针,但不删除为每行分配的数据。修复如下:

Matrix::~Matrix()
{
    for (int i = 0; i < noOfRows; ++i)
        delete[] data[i];
    delete [] data;
}

其他问题:

  1. 在操作员之间留出更多空间。您当前的代码将所有内容压缩在一起,使其难以阅读。例如:

for(int c=0;c<ref.noOfColumns;c++)可能是:for (int c=0; c < ref.noOfColumns; c++)

  1. 过度和不必要地使用 .this->

  2. 如果存在,那么也存在是有意义的。对于后者,只需 ,即可实现 ,制作一行或两行代码。Matrix::operator +Matrix::operator +=operator +operator +=operator +

  3. 这个答案说明了一种可能更好的内存分配方法,因为只进行了两次分配,分配的内存是连续的,并且会发生更少的内存碎片。

评论

0赞 BS e-Learning 3/29/2022
您已经删除了输入语句,那么我将这些语句放在哪里???要么在新功能中??或您观点中的任何其他选项。
0赞 PaulMcKenzie 3/29/2022
我删除了它们,因为它们在显示真正的问题是什么方面并不重要。把它们放回去。老实说,一个类不应该在中间放置输入。如果输入应该来自文件或其他方式怎么办?I/O 应该在类之外,相反,你的类应该具有允许设置数据的函数,而不管数据来自哪里。MatrixMatrix
0赞 BS e-Learning 3/29/2022
如果我把这段代码放在构造函数中,当我们创建一个 M3 对象时,它会再次询问输入数据,当我们调用 M3=M1+M2 时,它会再次询问,而最终结果却完美地显示出来。我想我必须从构造函数中删除此输入,并应将其放在一个单独的函数中。
0赞 PaulMcKenzie 3/29/2022
任何类代码中不应有输入。您应该具有设置值的其他成员函数。如果我想更改其中一个条目中的值,该怎么办?有没有办法做到这一点?不。MatrixMatrixMatrix
0赞 BS e-Learning 3/30/2022
我通过spearing setData()函数完成了这项工作。当我将 setData 用于 M3 时,它完美地显示加法,但如果我没有使用 setData 函数在 M3 对象中输入数据,它会在加法后显示无效输出。