添加两个矩阵会打印一列垃圾数据C ++

时间:2019-03-28 16:05:21

标签: c++ matrix multidimensional-array operator-overloading

我试图使用多维数组添加两个矩阵,并使加法运算符'+'和赋值运算符'='重载,但是,垃圾数据被传递给了我重载的赋值运算符函数。

我一直在阅读有关“复制和交换惯用语”的内容,但似乎无法找到解决问题的方法,因此,我宁愿单独使用+和=,而不是使用“ + =”我见过有人这样做,因为我将对矩阵使用其他算术,但是我想首先解决这个问题。

这是我的标题:

#ifndef Matrix_h
#define Matrix_h
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <utility>

class Matrix
{
private:
    int row;
    int column;
    double  ** elements;

public:
    Matrix();
    Matrix(int r, int c); //constructor
    Matrix(const Matrix& src);  //copy constructor
    ~Matrix(); //destructor

    Matrix& operator=(const Matrix& right);  // assignment operator
    int getRow() const;
    int getColumn() const;
    void setElement(int r, int c, double data);
    double getElement(int r, int c) const;
    Matrix& operator+(const Matrix& right); // calculates the sum of two matrices

};

#endif 

这是我的函数定义:

#include <string.h>
#include "matrix.h"
using namespace std;

Matrix::Matrix(int r, int c){ //defines the constructor to create a new matrix
    row = r;
    column = c;
    elements = new double*[row];
    for (int i=0; i<row; i++){
        elements[i] = new double[column];
    }
    for (int i=0; i<row; i++){
        for (int j=0; j<column; j++){
            elements[i][j] = 0;
        }
    }
}

Matrix::Matrix(const Matrix& src){ //defines the copying constructor
    row = src.row;
    column = src.column;
    elements = new double*[row];
    for (int i=0; i<row; i++){
        elements[i] = new double[column];
    }
    for (int i=0; i<row; i++){
        for (int j=0; j<column; j++){
            elements[i][j] = src.elements[i][j];
        }
    }
}

Matrix::~Matrix() { //defines the destructor
    for (int i=0; i<row; i++){
        delete[] elements[i];
    }

    delete[] elements;
};

void Matrix::setElement(int r, int c, double data) {
    elements[r][c] = data;
};

double Matrix::getElement(int r, int c) const {
    return elements[r][c];
}

int Matrix::getColumn() const {
    return column;
}

int Matrix::getRow() const {
    return row;
}

Matrix& Matrix::operator =(const Matrix& right) {

    if(this->elements != right.elements && column==right.column && row==right.row)
    {
        memcpy ( &this->elements, &right.elements, sizeof(this->elements) );
     }

    return *this;
}

Matrix& Matrix::operator +(const Matrix& right) {
    // first, make sure matrices can be added. if not, return original matrix
    if (this->row != right.row || this->column != right.column){
        cout << "Matrix sizes do not match.";
        return (*this);
    }

    Matrix sum(row, column);
    for (int i=0; i<this->row; i++){
        for (int j=0; j<this->column; j++){
            sum.elements[i][j] = this->elements[i][j] + right.elements[i][j];

        }
    }
    return sum;
}

我的主干简单地创建了一个4x4矩阵为1s的matrixA和一个矩阵4B的矩阵为2s的4x4并将它们添加到sum = matrixC处,这将导致一个4x4的3s矩阵。但是,这是我的结果:

matrixA
1   1   1   1   
1   1   1   1   
1   1   1   1   
1   1   1   1   

matrixB
2   2   2   2   
2   2   2   2   
2   2   2   2   
2   2   2   2   

matrixC before addition
0   0   0   0   
0   0   0   0   
0   0   0   0   
0   0   0   0   

matrixC after addition
1.0147e-316 3   3   3   
1.0147e-316 3   3   3   
1.0147e-316 3   3   3   
1.0147e-316 3   3   3

当我测试它以查看将哪些元素传递给'='函数中的'right'时,我注意到与matrixC第一列相似的数据。我认为我不完全理解此处涉及的引用的传递,因此我希望对此有所帮助。

4 个答案:

答案 0 :(得分:2)

嗯,我的CLang编译器警告我operator +(const Matrix& right)返回对未定义行为的临时引用。

您必须返回一个普通对象而不是引用:

Matrix operator=(const Matrix& right);  // assignment operator

答案 1 :(得分:2)

Matrix& Matrix::operator +(const Matrix& right) {
    // ...

    Matrix sum(row, column);
    // ...
    return sum;
}

您要返回对自动本地(sum)的引用。

您可以看到算术运算符here的规范形式,并且加法应类似于

Matrix Matrix::operator+(const Matrix &b) const;

还有许多其他问题,在其他答案中也有提到,但是您当前的operator+唯一可靠产生的就是不确定的行为。

答案 2 :(得分:2)

您的赋值运算符已损坏(并且在逻辑上有缺陷)。

从逻辑上讲,这是有缺陷的,因为无论m1 = m2的先前状态如何,m1 == m2之类的赋值都将导致m1。您的实现仅在大小相同时尝试复制。您应该在作业左侧调整矩阵的大小。

您的操作员还没有正确使用memcpymemcpy(dest, src, count)会将连续数据从地址src复制到地址dest。您提供的地址是指向int 的指针的指针的地址,指向int连续块的 not 指针的指针的地址。这里memcpy根本就没有任何线索可分为两个层次。另外,sizeof(this->elements)sizeof(int**),这将是大约4或8个字节的常数,这似乎也错了。要解决此问题,我只使用一组简单的for循环即可。

Matrix& Matrix::operator=(const Matrix& other){
    // attempt to acquire memory before modifying (for exception safety)
    int** temp = new int*[other.row];
    for (int i = 0; i < other.row; ++i){
        temp[i] = new int[other.col];
    }

    // cleanup
    for (int i = 0; i < row; ++i){
        delete[] elements[i];
    }
    delete[] elements;

    // copy data
    elements = temp;
    row = other.row;
    col = other.col;
    for (int i = 0; i < row; ++i){
        for (int j = 0; j < col; ++j){
            elements[i][j] = other.elements[i][j];
        }
    }

    return *this
}

另一个重要说明:您的operator+返回对局部变量的引用。这非常糟糕,但是C++ doesn't protect you from it。您应该只按值返回sum

在现代C ++中,我们通常更喜欢使用std::vector<std::vector<int>>之类的替代手动内存管理的更安全的方法,这可以无缝地强制正确使用并从您身上救出自己。

答案 3 :(得分:0)

一个提示:如果将矩阵存储为一个数组double m[rows * columns],则实现将更加简单。

索引[row][column]m[row * columns + column]

求和只是将两个数组按元素求和(本质上是向量求和)。