【问题标题】:Identifying Behavior of Matrix Variable Assignment [duplicate]识别矩阵变量分配的行为
【发布时间】:2019-11-09 16:32:39
【问题描述】:

我正在尝试开发自己的自定义“矩阵”类,用于 C++ 中的模式识别和神经网络。在大多数情况下,它工作正常,但是在分配变量时我的代码遇到了问题。一种分配变量的方法不起作用,它似乎使我的代码崩溃。

为了提供一点背景知识,我的矩阵是一个名为 Matrix 的类中的双精度数组。我添加了适当的构造函数和析构函数,以及一种操作矩阵各个元素的方法。我的主要问题是分配类变量。假设我有两个矩阵:A 和 B。目标是将内容从 A 复制到 B。如果我尝试一种方法,我的代码将按预期工作。如果我尝试其他方式,我的代码在执行后尝试释放时会崩溃。

class Matrix{
    public:
        //Constructors
        Matrix();                   //EMPTY Matrix
        Matrix(int, int);           //Matrix WITH ROW AND COL
        ~Matrix();                  //Destructor

        void operator= (const Matrix &);

        double & operator() (int X,int Y) const{return this->array[X][Y]; }
        void print() const;                       //Print the Matrix
    private:
        double **array; 
        int nrows;
        int ncols;
        int ncell;
};


//When you want to copy a matrix to another Matrix variable
void Matrix::operator= (const Matrix &M) {

    if(this->array != NULL){
        for(int i=nrows-1; i>=0; i--)   free(this->array[i]);
        free(this->array);
        this->array = NULL;
    }

    //Using parameters from the matrix being copied, rebuild it
    this->nrows = M.nrows;  this->ncols = M.ncols;  this->ncell = M.ncell;

    //First, create an ariray of double* for the rows
    this->array = (double **) malloc(sizeof(double *)*(this->nrows));

    //Next, go through each 'row', and copy over elements
    for(int i=0; i<(this->nrows); i++){
        this->array[i] = (double *) malloc(sizeof(double)*(this->ncols));
        for(int j=0; j<(this->ncols); j++){
            this->array[i][j] = M.array[i][j];
        }
    }

}


int main(int argc, char *argv[]){ //C.applyFunc(SP);

    printf("\n\nCreating  Matrix A\n");
    Matrix A(1,3);      A(0,0) = 8;

    printf("\n\nPRINTING \n\n");    A.print();

    printf("\n\nCreating B\n\n");

    Matrix B = A; //THIS IS THE PROBLEM RIGHT HERE!!!

    //Matrix B;
    //B = A;

    printf("\n\nPRINTING B\n\n");   B.print(); B(0,0) = 123;
    printf("PRINTING A AGAIN\n\n"); A.print();
    printf("PRINTING B AGAIN\n\n"); B.print();
    return 0;
}

在我的代码中,我发布了我的类、'=' 的运算符重载和我的主函数。其他功能不那么重要,只是打印矩阵等等。如果你觉得它有帮助,我稍后会包含它。在这里,在我的主代码中,矩阵 A 被分配为 1x3 行矩阵,将 A[0][0] 设置为 8。打印出矩阵来验证这一点。现在,当我将 B 分配给 A 时,如未注释掉的行所示,我希望 B 和 A 具有相同的值。后来,我把 B[0][0] 改成 123。

最后,我希望 A 为 [8, 0, 0] 而 B 为 [123, 0, 0]。但是,当我再次打印出 A 和 B 时,它们都是相同的,[8,0,0]。似乎不知何故,B指向A,所以当A在B之后被释放时,它已经被释放并且崩溃了。但是,当我运行注释代码并以这种方式分配 B 时,我的代码完全按照我的预期工作。当我调用 'Matrix B = A' 使其与下面的注释代码不同时,到底发生了什么?

【问题讨论】:

  • 您定义了复制赋值操作符,但没有定义复制操作符。您认为的赋值可能会被智能编译器优化为复制构造。
  • @CuriouslyRecurringThoughts 实际上需要在较新的 C++ 标准中“优化”。如,Matrix B = A; 不是赋值,而是(复制)初始化,因此直接调用Matrix(const Matrix&amp;)
  • 虽然您的代码可能适用于教育目的,但没有理由 1. 在 C++ 中使用 mallocfree; 2.为每个矩阵行分配(分配一个大小cols*rows会更好); 3. 进行手动内存管理(std::vector 在这里完成您需要的一切)和 4. 在每个成员访问前加上 this-&gt;。所有这些事情都令人不悦或更糟。
  • @MaxLanghof 感谢您的澄清。
  • @MaxLanghof 感谢您的回复。我想我是这样做的,因为我之前练习了一点 C,所以我刚刚习惯了这种内存管理方式。

标签: c++ matrix operator-overloading assignment-operator


【解决方案1】:

嗯,简而言之,

Matrix B = A;

不是关于执行赋值,而是复制构造函数,如果我没有遗漏什么,它没有在你的类中定义。

【讨论】:

  • 感谢您的回复。我明白你现在的意思了。依稀记得拷贝构造函数,但是有段时间忘记怎么用了,还是真的记得实现它。谢谢。到时候我会做一些研究。
  • @user101402 不客气。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-02
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
相关资源
最近更新 更多