c++ 自定义Matrix类中的复制构造函数问题

gstyhher  于 2023-03-20  发布在  其他
关注(0)|答案(2)|浏览(180)

我有一个自定义的矩阵类,它本身工作得很好。我遇到的问题是,当我试图创建一个由另一个矩阵定义的新矩阵时,整个矩阵没有被复制。
矩阵本身基本上只是一个指向一个双精度型的一维数组的指针,我有一个自定义函数来查找正确的m x n索引。我创建了一个复制构造函数,并重载了=运算符。我觉得只有部分矩阵被复制,这真的很奇怪。
问题可能是我如何对待我的指针,因为我没有完全掌握它。
当我尝试这样做时:

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);
};

这是类的定义:

#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;
}
js81xvg6

js81xvg61#

复制构造函数中的此语句

*matrix = *other.matrix;

相当于

matrix[0] = other.matrix[0];

也就是说,它只设置新创建数组的一个元素,但您需要复制所有元素。
你可以用for循环作为例子

for ( int i = 0; i < r * c; i++ )
{
    matrix[i] = pther.matrix[i];
}

或者可以使用标头<algorithm>中声明的标准算法std::copy

#include <algorithm>

//...

std::copy( other.matrix, other.matrix + r * c, matrix );

由于您使用的是基本类型double,因此您还可以使用标头<cstring>中声明的标准C函数memcpy,如

#include <cstring>

//...

std::memcpy( matrix, other.matrix, r * c * sizeof( double ) );

析构函数还应释放分配的内存

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

否则,复制赋值运算符定义如下

Matrix& Matrix::operator=(Matrix rhs){
    r = rhs.r;
    c = rhs.c;
    swap(matrix, rhs.matrix);
    return *this;
}

将产生内存泄漏。
在这个构造函数中

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;
    }
}

这个for循环

//fills with zeros
    for(int i = 0; i<r*c; i++){
        matrix[i] = 0;
    }

是冗余的。已分配数组的元素已在此语句中设置为零

matrix = new double[r*c]{};
bybem2ql

bybem2ql2#

这不会将数据从一个阵列复制到另一个阵列:
*matrix = *other.matrix;
复制数据memcpy或使用std::copy需要循环:
std::copy(other.matrix, other.matrix + r*c, matrix);

相关问题