简体   繁体   English

为类内的动态数组复制构造函数和operator =

[英]Copy constructor and operator= for a dynamic array inside a class

I need some help to implement a copy constructor and a operator= for my dynamic array inside my class. 我需要一些帮助来为我的类中的动态数组实现复制构造函数和operator =。 Im not allowed to use a vector at this point 我目前不允许使用向量

Here is mye code: Class: 这是mye代码:类:

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

And my code: 而我的代码:

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

Would something like this work? 这样的事情行吗?

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

Im also going to overload the operator += and +. 我也将重载运算符+ =和+。 I've tried to implement this as: 我尝试将其实现为:

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

Would something like this work? 这样的事情行吗? Is it better to overload the operators as a part of the class, a friend of the class or just outside the class? 将操作员作为班级的一部分,班级的朋友还是仅在班级之外重载会更好吗?

Any help is appriciated. 任何帮助都适用。

Why did you delete the other question? 为什么删除另一个问题? I hope it was just an error: (see the EDIT at end) 我希望这只是一个错误:(请参阅最后的编辑)

Yes, you have many issues in your code, and even in your design. 是的,您的代码甚至设计中都有很多问题。

Just to give you an idea: 只是给你一个想法:

Your Matrix have no copy constructor (or move) and not “ = ” too. 您的矩阵没有复制构造函数(或移动),也没有“ = ”。 They are: 他们是:

Matrix(const Matrix &m);

And (move constructor): 和(移动构造函数):

Matrix(Matrix &&m);

And

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

If you don't define these special functions, the compiler will define it for you. 如果您没有定义这些特殊功能,则编译器将为您定义它。 But they will only apparently work. 但是它们显然只会起作用。 The program compile but work wrong ( shallow vs. deep copy problem , and pass by value or by reference ). 程序编译但工作不正确( 浅层复制与深层复制问题 ,并通过值或引用传递 )。 I gees you use new in the constructor to build the matrix private array. 我想您在构造函数中使用new来构建matrix私有数组。 And in the destructor you delete[]matrix . 然后在析构函数中delete[]matrix Each time you pass a Matrix by value it get copy-ed using the complier generated copy constructor, with just copy the value of the members of Matrix , thus copying the value of the pointer matrix but not the array. 每次通过值传递Matrix ,都会使用编译器生成的复制构造函数进行复制,只复制Matrix成员的值,从而复制指针matrix的值,而不复制数组。 At the end of the call this local copy will be destructed, and your original matrix get deleted!! 在通话结束时,此本地副本将被销毁,原始矩阵将被删除!! This is just one of the many problems. 这只是许多问题之一。 Sufficient for you to sit, read a litter more and try again latter. 您足够坐下,多读一本垃圾,然后再试一次。 A "simple" fix maybe to replace “简单”修复程序可能会取代

 double *matrix;

by 通过

std::vector<double> matrix;

Now the compiler generated functions will work a lot better. 现在,编译器生成的函数将更好地工作。

And yes, if you want to use [] with Matrix you need to define it. 是的,如果要在Matrix使用[] ,则需要对其进行定义。 And += is a binary operator, that take one parameter (the left is always this , a pointer to the object with call it). +=是一个二元运算符,带有一个参数(左边始终是this ,指向调用它的对象的指针)。 Here you want just a free +() with 2 arguments or a member +() with one. 在这里,您只需要带有两个参数的免费+()或带有一个参数的成员+() Hope this help you. 希望这对您有所帮助。 Ask again. 再问一遍。

EDIT: Does this work as an operator= ? 编辑:这是否可以作为operator=

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

No, this will copy only the first double. 不,这只会复制第一个双精度数。 You will need a loop over the entery array and copy each element. 您将需要在Entery数组上循环并复制每个元素。 And first you need to be sure that the size of the matrixes are compatible. 首先,您需要确保矩阵的大小兼容。 (If you use the vector matrix=m.matrix will work.). (如果使用vector matrix=m.matrix则可以使用。)。 A fix for your copy constructor could be: 您的副本构造函数的修复方法可能是:

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

} 

And to move: 并移动:

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

This move can dramatically improve the efficiency of coping Matrixes when you don't care about the original value, with is for example the case with temporal objects. 当您不关心原始值时,例如临时对象的情况,此举可以大大提高应对矩阵的效率。 In this case, you don't need to iterate copying each array element: you simple steal the full array. 在这种情况下,您不需要迭代复制每个数组元素:您只需窃取整个数组。 The good thing about it is that in most situations the compiler will pick “automatically” the correct variant (copy or move) for you. 这样做的好处是,在大多数情况下,编译器将为您“自动”选择正确的变体(复制或移动)。

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

This will only assign the first element of lhs' matrix to be the same as the first element of the rhs' matrix. 这只会将lhs矩阵的第一个元素分配为与rhs'矩阵的第一个元素相同。 On top of that, this would require that both matrices have been initialized with the same number of rows and columns. 最重要的是,这将要求两个矩阵都使用相同数量的行和列进行初始化。 You can use memcpy or a loop to assign all elements. 您可以使用memcpy或循环来分配所有元素。

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

This will fail because you are not allocating enough memory for the matrix member of the newly constructed instance (unless the other matrix is a 1x1 matrix). 这将失败,因为您没有为新构造的实例的矩阵成员分配足够的内存(除非另一个矩阵是1x1矩阵)。 Assuming the matrices are stored in row-major order, it should look like this: 假设矩阵以行优先顺序存储,则它应如下所示:

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

EDIT: Just to make sure, here's how I would do the assignment operator: 编辑:只是为了确保,这就是我要做赋值运算符的方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM