-1

我需要一些帮助来为我的类中的动态数组实现复制构造函数和 operator=。我此时不允许使用向量

这是我的代码: 类:

    class Matrix{
    private:
        int rows;
        int columns;
        double* matrix;
    public:
        Matrix();
        explicit Matrix(int N);
        Matrix(int M, int N);
        void setValue(int M, int N, double value);
        double getValue(int M, int N);
        bool isValid() const;
        int getRows();
        int getColumns();
        ~Matrix();
        friend ostream& operator<<(ostream &out, Matrix&matrix1);       
};

我的代码:

Matrix::Matrix(){
    matrix = NULL;
}

Matrix::Matrix(int N){
    matrix = new double[N * N];
    rows = N;
    columns = N;

    for(int i = 0; i < N; i++){
        for(int j = 0; j < N; j++){
            if(i==j)
                matrix[i * N + j] = 1;
            else
                matrix[i * N + j] = 0;
        }
    }
}

Matrix::Matrix(int M, int N){
    matrix = new double[M * N];
    rows = M;
    columns = N;

    for(int i = 0; i < M; i++){
        for(int j = 0; j < N; j++)
            matrix[i * N + j] =  0;
    }
}

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

void Matrix::setValue(int M, int N, double value){
    matrix[M * columns + N] = value;
}

double Matrix::getValue(int M, int N){
    return matrix[M * columns + N];
}

bool Matrix::isValid() const{
    if(matrix==NULL)
        return false;
    else
        return true;
}

int Matrix::getRows(){
    return rows;
}

int Matrix::getColumns(){
    return columns;
}

ostream& operator<<(ostream &out, Matrix&matrix1){
    if(matrix1.isValid())
        for(int i = 0; i < matrix1.getRows(); i++){
            for(int j = 0; j < matrix1.getColumns(); j++)
                out << matrix1.getValue(i,j) << "\t";
            out << endl;
        }
    else
        out << "Matrisen er ikke gyldig."; //the matrix is not valid
    return out;
}

像这样的东西会起作用吗?

Matrix &operator=(const Matrix &m) {*(this->matrix) = *(m.matrix);}
Matrix(const Matrix &rhs) : matrix(0) {
        this->matrix = new double();
        *(this->matrix) = *(rhs.matrix);
    }

我还要重载运算符 += 和 +。我试图将其实现为:

const Matrix operator+=(Matrix matrix1, Matrix matrix2){
        if(!matrix1.isValid() || !matrix2.isValid()){
            cout << "En av matrisene er ugyldig"; //one of the matrices are invalid
            return Matrix::Matrix(); //returning a NULL matrix
        }
        else{
            if(matrix1.getColumns()==matrix2.getColumns() && matrix1.getRows()==matrix2.getRows()){
                Matrix temp(matrix1.getRows(), matrix1.getColumns());
                for(int i = 0; i < matrix1.getRows(); i++){
                    for(int j = 0; j < matrix1.getColumns(); j++)
                        temp.setValue(i,j,(matrix1.getValue(i,j) + matrix2.getValue(i,j)));
                }
                return temp;
            }
            else{
                cout << "Matrisene har ikke samme dimensjon"; //the matrices does not have the same dimensions
                return Matrix::Matrix();
            }
        }
    }
    const Matrix operator+(Matrix matrix1, Matrix matrix2){
        return matrix1 += matrix2;
    }

像这样的东西会起作用吗?将运算符重载为类的一部分、类的朋友还是类之外更好?

任何帮助都会得到帮助。

4

2 回答 2

1

你为什么删除另一个问题?我希望这只是一个错误:(见最后的编辑)

是的,您的代码甚至设计中都有很多问题。

只是给你一个想法:

您的 Matrix 没有复制构造函数(或移动),也没有“<code>=”。他们是:

Matrix(const Matrix &m);

和(移动构造函数):

Matrix(Matrix &&m);

Matrix& operator=( const Matrix &m);
Matrix& operator=( Matrix &&m);

如果你不定义这些特殊函数,编译器会为你定义。但它们只会在表面上起作用。程序编译但工作错误(浅拷贝与深拷贝问题,并按值或按引用传递)。我很高兴您new在构造函数中使用来构建matrix私有数组。而在析构函数中你delete[]matrix。每次Matrix通过值传递时,它都会使用编译器生成的复制构造函数进行复制,只需复制 的成员的值Matrix,从而复制指针的值matrix但不是数组。在调用结束时,此本地副本将被破坏,并且您的原始矩阵将被删除!!这只是众多问题之一。足够你坐下来,多读一读,然后再试一次。一个“简单”的修复可能会替换

 double *matrix;

经过

std::vector<double> matrix;

现在编译器生成的函数会更好地工作。

是的,如果你想与你一起使用[]Matrix你需要定义它。And+=是一个二元运算符,它接受一个参数(左边总是this,一个指向调用它的对象的指针)。在这里,您只想要一个+()带有 2 个参数的免费或一个+()带有一个参数的成员。希望这对您有所帮助。再问一遍。

编辑:这可以作为一个operator=吗?

Matrix &operator=(const Matrix &m) {*matrix = *(m.matrix);}

不,这只会复制第一个双精度数。您将需要对 entery 数组进行循环并复制每个元素。首先,您需要确保矩阵的大小是兼容的。(如果你使用vector matrix=m.matrix意志工作。)。您的复制构造函数的修复可能是:

Matrix::Matrix(const Matrix &m):   rows    (m.rows), 
                                   columns (m.columns), 
                                   matrix  (new double[rows* columns]) 
{
    for(int i = 0; i < rows; i++)
        for(int j = 0; j < columns; j++)
            matrix[i * columns + j] =  m.matrix[i * columns + j];

} 

并移动:

Matrix::Matrix(     Matrix &&m):   rows    (m.rows), 
                                   columns (m.columns), 
                                   matrix  (m.matrix) 
{
     m.matrix=nullptr;
     m.rows= m.columns=0;
} 

当您不关心原始值时,这一举措可以显着提高处理矩阵的效率,例如时间对象的情况。在这种情况下,您不需要重复复制每个数组元素:您只需窃取整个数组。这样做的好处是,在大多数情况下,编译器会为您“自动”选择正确的变体(复制或移动)。

于 2013-03-13T11:02:05.863 回答
1
Matrix &operator=(const Matrix &m) {*(this->matrix) = *(m.matrix);}

这只会将 lhs 矩阵的第一个元素分配为与 rhs 矩阵的第一个元素相同。最重要的是,这将要求两个矩阵都已使用相同数量的行和列进行初始化。您可以使用 memcpy 或循环来分配所有元素。

Matrix(const Matrix &rhs) : matrix(0) {
    this->matrix = new double();
    *(this->matrix) = *(rhs.matrix);
}

这将失败,因为您没有为新构造的实例的矩阵成员分配足够的内存(除非另一个矩阵是 1x1 矩阵)。假设矩阵以行优先顺序存储,它应该如下所示:

Matrix(const Matrix &rhs) : matrix(0), rows(rhs.rows), columns(rhs.columns) {
    this->matrix = new double[rows * columns];
    for (size_t r = 0; r < rows; r++) {
       for (size_t c = 0; c < columsn; c++) {
          this->matrix[r * columns + c] = rhs.matrix[r * columns + c];
       }
    }
}

编辑:只是为了确保,这是我将如何做赋值运算符:

Matrix &operator=(const Matrix &m) {
    if (rows * columns != m.rows * m.columns) {
        delete [] this->matrix;
        this->matrix = new double[m.rows * m.columns];
    }
    rows = m.rows;
    columns = m.columns;
    for (size_t r = 0; r < rows; r++) {
       for (size_t c = 0; c < columsn; c++) {
          this->matrix[r * columns + c] = m.matrix[r * columns + c];
       }
    }
    return *this;
}
于 2013-03-13T11:06:10.537 回答