矩阵类编写构造函数,解构器和复制构造函数的方式

the way of writing constructor, deconstructor and copy constructor for matrix class

本文关键字:构造函数 复制 方式      更新时间:2023-10-16

我正在尝试为矩阵类创建一个构造函数,破坏者和复制构造函数,我不确定我是否做得很好。

特别是我不确定两件事:

  1. destructor是否应该为复制构造者中分配的内存免费内存?

  2. 关于行Mat[i][j]=other[i][j](请参见下面的代码),我想知道是否应该写Mat[i][j]=other.Mat[i][j]

class Matrix
{
private:
    int rows;
    int cols;
    int **Mat;
public:
    Matrix (const int &rows,const int &cols);
    Matrix (const Matrix &other);
    ~Matrix ();
};
Matrix::Matrix(const int &n_rows,const int &n_cols) //constructor of class Matrix
{
    rows=n_rows; 
    cols=n_cols;
    Mat=new int* [cols];
    for(int i =0;i<rows;i++)
       Mat[i]=new int[cols];
    for(int i=0;i<rows;i++)
      for(int j=0;j<cols;j++)
        Mat[i][j]=0;            
}
Matrix::~Matrix () //destructor
{
    for(int i =0;i<rows;i++)
        delete Mat[i];
    delete[] Mat;
}
Matrix::Matrix(const Matrix &other)  //copy constructor
{
    cols=other.cols;
    rows=other.rows;
    Mat=new int* [other.rows];
    for(int i =0;i<other.rows;i++)
       Mat[i]=new int[other.cols];
    for(int i=0;i<other.rows;i++)
      for(int j=0;j<other.cols;j++)
            Mat[i][j]=other[i][j];
}

1)我认为解构器仅擦除仅属于的对象,因为复制构造的对象具有自己的驱动器。

2)是的,Mat[i][j] = other.Mat[i][j]是正确的,但是如果您希望您的程序更快一点,请尝试使用指针(我知道这不是很容易^^)

a 构造函数是一个类操作,可以初始化特定类的对象实例。

对象创建涉及多个操作,例如:

  1. 分配内存以存储新对象的结构
  2. 正确初始化对象的属性。

a 复制构造函数是构造函数的一种特殊情况,它的实例与输入参数相同。 - 它仍然是一个构造函数,执行上述相同的操作。

a destructor 是一个类操作,当对象不再使用时,负责最终确定对象。

可以使用其定义的任何构造函数,即普通构造函数或复制构造函数来构造一个对象。当您删除该对象时,应在破坏者中对类分配的任何内存进行交易。

希望这会有所帮助。

至于与代码相关的问题;调用复制构造函数时,您将通过类的现有对象实例。由于您没有实施任何操作员过载,因此您可以访问对象的属性,如#2中所说的。

我不确定这是否完全回答您的问题,但我希望它会有所帮助。

  1. 是。物体仍然分配的任何东西都应释放在灾难中。分配了哪个构造函数都没关系。

  2. 是的,您需要使用Mat[i][j]=other.Mat[i][j],尤其是因为您尚未为课程定义任何operator[]

您还需要根据"三个规则"添加复制分配运算符,该操作员基本上指出:

类需要用户定义的驱动器,用户定义的复制构造函数或用户定义的复制分配运算符,它几乎可以肯定需要所有三个。

尝试以下操作:

class Matrix
{
private:
    int rows;
    int cols;
    int **Mat;
public:
    Matrix (int n_rows, int n_cols);
    Matrix (const Matrix &other);
    ~Matrix ();
    Matrix& operator=(const Matrix &rhs);
    // alternatively:
    // Matrix& operator=(Matrix rhs);
};
Matrix::Matrix(int n_rows, int n_cols)
{
    rows = n _rows; 
    cols = n_cols;
    Mat = new int*[rows];
    for(int i = 0; i < rows; ++i)
    {
       Mat[i] = new int[cols];
       for(int j = 0; i < cols; ++j)
           Mat[i][j] = 0;
    }
}
Matrix::Matrix(const Matrix &other)
{
    rows = other.rows;
    cols = other.cols;
    Mat = new int*[rows];    
    for(int i = 0; i < rows; ++i)
    {
        Mat[i] = new int[cols];
        for(int j = 0; j < cols; ++j)
            Mat[i][j] = other.Mat[i][j];
    }
}
Matrix::~Matrix()
{
    for(int i = 0; i < rows; ++i)
        delete Mat[i];
    delete[] Mat;
}
Matrix& Matrix::operator=(const Matrix &rhs)
{
    if (&rhs != this)
    {
        Matrix temp(rhs);
        std::swap(Mat, temp.Mat);
        std::swap(rows, temp.rows);
        std::swap(cols, temp.cols);
    }
    return *this;
}
// alternatively:
/*
Matrix& Matrix::operator=(Matrix rhs)
{
    std::swap(Mat, rhs.Mat);
    std::swap(rows, rhs.rows);
    std::swap(cols, rhs.cols);
    return *this;
}
*/

一个更好的解决方案是完全不直接使用new[]/delete[]。改用std::vector,让它为您处理所有内容,从而允许您的课程遵循"零规则":

具有自定义驱动器,复制/移动构造函数或复制/移动分配操作员的类应专门处理所有权(根据单个责任原则遵循)。其他类不应具有自定义驱动器,复制/移动构造函数或复制/移动分配操作员。

class Matrix
{
private:
    std::vector<std:vector<int> > Mat;
public:
    Matrix (int n_rows, int n_cols);
};
Matrix::Matrix(int n_rows, int n_cols)
{
    Mat.resize(n_rows);
    for(int i = 0; i < n_rows; ++i)
       Mat[i].resize(n_cols, 0);
    /* alternatively:
    Mat.resize(n_rows, std::vector<int>(n_cols, 0));
    */
}