I have this problem: I wrote code to multiply two matrices. To do this, I created a class in which I declared the fields of the matrix, the function of reading from a file, writing, and overloading the multiplication operator.

It seems everything worked. But the teacher said that there must be a destructor in the classroom. In general, after I wrote the destructor, the program crashed. As I understand it, the problem is that the destructor deletes the same address twice. How do I code to make the program work with the destructor? I do not quite understand. Please help me edit the code.

#include<iostream> #include<fstream> #include <cmath> using namespace std; class Matrix { private: void method(); private: double** matr; //matrix int rown; //rown int column; //column std::string m_name; public: Matrix(const char *name) { m_name = name; matr = NULL; rown = column = 0; cout << __FILE__ << ":" << __LINE__ << " CONSTRUCTOR " << m_name.data() << " " << matr << endl; } void allocate(int in_rown, int in_column) { rown = in_rown; column = in_column; matr = new double*[rown]; for (int i = 0; i < rown; i++) { matr[i] = new double[column]; } cout << __FILE__ << ":" << __LINE__ << " ALLOCATOR " << m_name.data() << " " << matr << endl; } Matrix operator*(Matrix & mult); void read_matrix(const char*filename); void write_matrix(const char*filename) const; ~Matrix() { cout << __FILE__ << ":" << __LINE__ << " DESTRUCTOR " << m_name.data() << " " << matr << endl; if (matr != NULL) { for (int i = 0; i < rown; i++) { delete[] matr[i]; } delete[] matr; } } }; Matrix Matrix::operator*(Matrix & mult) { Matrix result("result"); result.allocate(rown, mult.column); for (int i = 0; i < result.rown; i++) { for (int k = 0; k < result.column; k++) { result.matr[i][k] = 0; for (int j = 0; j < result.column; j++) { result.matr[i][k] += matr[i][j] * mult.matr[j][k]; } } } return result; } void Matrix::read_matrix(const char* filename) { ifstream in(filename); in >> rown; in >> column; allocate(rown, column); //Считаем матрицу из файла for (int i = 0; i < rown; i++) for (int j = 0; j < column; j++) in >> matr[i][j]; in.close(); return; } void Matrix::write_matrix(const char* filename) const { ofstream on(filename); on << rown << '\t' << column << endl; //запишем матрицу в файл for (int i = 0;i < rown;i++) { for (int k = 0;k < column;k++) { on << matr[i][k] << '\t'; } on << endl; } on.close(); return; } int main(int argc, char*argv[]) { if (argc == 4) { Matrix input1("input1"); Matrix input2("input2"); input1.read_matrix(argv[1]); input2.read_matrix(argv[2]); Matrix a("a"); a = input1*input2; /*Matrix b;*/ a.write_matrix(argv[3]); } system("pause"); return 0; } 

    1 answer 1

    In this sentence

     a = input1*input2; 

    the default copying assignment operator created by the compiler is used; the result of multiplying two matrices - a temporary object of the same class - is assigned to object a .

    The copying assignment operator defined by the compiler simply copies the data of one object to another member-by-member. As a result, in the above sentence, the two objects will have copies of each other's pointers.

    After this assignment is completed, the temporary object will be deleted and a destructor will be called for it, which will release the allocated memory.

    When object a is deleted, a destructor will also be called for it, which will attempt to free the already freed memory at the same address.

    When you deal with pointers in the class and manually allocate the memory addressed by these pointers, then you need to write explicitly in addition to the destructor at least also the copy constructor and the copy assignment operator, which will make a "deep" copy of the objects.

    For your specific example, in order for your code to be executed without the error described, it will be sufficient to write a moving assignment operator.

    For example,

     Matrix & operator =( Matrix &&rhs ) { if ( this != &rhs ) { std::swap( this->rown, rhs.rown ); std::swap( this->column, rhs.column ); std::swap( this->matr, rhs.matr ); } return *this; }