Ошибка в работе деструктора

219
18 марта 2018, 21:23

Помогите пожалуйста разобраться в данной ошибке. Сам еще только учусь, поэтому потратил большое количество времени, пытаясь разобраться в этом.

class Matrix
{
private:
   double** M;
public:
int n;
int m;
class wrong_size{};
class wrong_count{};
Matrix(int height, int width);
~Matrix();
Matrix operator+(Matrix& A);
Matrix operator-(Matrix& A);
Matrix operator*(Matrix& A);
double* operator[](int i);
friend istream& operator >>(istream& input, Matrix& A);
friend ostream& operator <<(ostream& output, Matrix& A);
};
Matrix::Matrix(int height = 3, int width = 4) : n(height), m(width)
{
M = new double*[n];
for (int i = 0; i < n; i++)
    M[i] = new double[m];
}
Matrix::~Matrix()
{
for (int i = 0; i < n; i++)
    delete[] M[i];
delete[] M;
cout << "Delete";
}
Matrix Matrix::operator+(Matrix& A)
{
if(n == A.n && m == A.m)
{
    Matrix X(n, m);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            X[i][j] = M[i][j] + A[i][j];
    return X;
}
else throw wrong_size();
}
Matrix Matrix::operator-(Matrix& A)
{
if (n == A.n && m == A.m)
{
    Matrix X(n, m);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            X[i][j] = M[i][j] - A[i][j];
    return X;
}
else throw wrong_size();
}
Matrix Matrix::operator*(Matrix& A)
{
if(A.n == m)
{
    Matrix X(n, m);
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
        {
            X[i][j] = 0;
            for (int k = 0; k < n; k++)
                X[i][j] = M[i][k] * A[k][j];
        }
    return X;
}
else throw wrong_count();
}
double* Matrix::operator[](int i)
{
return M[i];
}
istream& operator>>(istream& input, Matrix& A)
{
for (int i = 0; i < A.n; i++)
    for (int j = 0; j < A.m; j++)
        input >> A.M[i][j];
return input;
}
ostream& operator<<(ostream& output, Matrix& A)
{
for (int i = 0; i < A.n; i++) {
    for (int j = 0; j < A.m; j++)
        output << A[i][j] << " ";
    output << endl;
}
return output;
}
void function(Matrix& A)
{
for (int i = 0; i < A.n; i++) 
    for (int j = 0; j < A.m; j++)
        if (fmod(A[i][j], 2) > 0)
        {
            A[i][j] *= 2;
            cout << A[i][j] << " ";
        }   
}
void main()
{
setlocale(LC_ALL, "Russian");
try {
    int n1, m1;
    cout << "Введите n1 & m1: ";
    cin >> n1 >> m1;
    Matrix M1(n1, m1);
    cin >> M1;
    int n2, m2;
    cout << "Введите n2 & m2: ";
    cin >> n2 >> m2;
    Matrix M2(n2, m2);
    cin >> M2;
    Matrix M3;
    int choice;
    cout << "Выберите 
    действие:\n1.Сумма\n2.Разность\n3.Произведение\n4.Увеличение нечетных 
    элементов\n";
    cin >> choice;
    switch (choice)
    {
    case 1:
        M3 = M1 + M2;
        cout << "Сумма: " << endl << M3;
        break;
    case 2:
        M3 = M1 - M2;
        cout << "Разность: " << endl << M3;
        break;
    case 3:
        M3 = M1 * M2;
        cout << "Произведение: " << endl << M3;
        break;
    case 4:
        Matrix M4;
        cin >> M4;
        function(M4);
        break;
    }
}
catch(Matrix::wrong_size)
{
    cout << "Вы ввели неправильный размер матриц." << endl;
}
catch(Matrix::wrong_count)
{
    cout << "Ошибка, во время вычисления" << endl;
}
system("pause");
}
Answer 1

Нет оператора присваивания и копирующего конструктора; в результате их генерирует компилятор и они выполняют поверхностное копирование - не матрицы, а указателя на нее.

После чего в деструкторе все и валится из-за двойного удаления.

Это так, навскидку. Не гарантирую, что на этом ошибки заканчиваются - смотрел поверхностно, как сгенерированный конструктор :)

Update

А что именно должно быть в копирующем конструкторе?

Главное - создание матрицы, т.е. выделение памяти, с последующим копированием в нее элементов копируемой матрицы.

В операторе присваивания - если хватает имеющейся выделенной для матрицы памяти - перезапись ее соответствующими элементами, если нет - ее освобождение, и выделение новой с последующим копированием в нее элементов копируемой матрицы.

Update2

Ну что тут непонятного?

Matrix::Matrix(const Matrix&Mt) : n(Mt.n), m(Mt.m)
{
    M = new double*[n];
    for (int i = 0; i < n; i++)
        M[i] = new double[m];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            M[i][j] = Mt.M[i][j];
}

Примерно так. Присваивание - аналогично, только с учетом, что память уже выделена.

READ ALSO
Подключение *.pas файла к проекту в C++ Builder

Подключение *.pas файла к проекту в C++ Builder

Имеется проект в C++ Builder, также имеется файл форматаpas содержащий довольно большое количество нужного кода

172
Проблемы с QTime C++/Qt

Проблемы с QTime C++/Qt

Есть конструктор для класса, в который передается начальное время:

176
Как добавить в свой проект библиотеку libosmscout?

Как добавить в свой проект библиотеку libosmscout?

Как добавить в свой проект библиотеку libosmscout ? Я использую IDE Qt Creator, у меня операционная система WindowsПишу я на C++

188
Проблема с сервером WildFly 11

Проблема с сервером WildFly 11

Всем привет! Такой вопрос, есть сайт, написан на HTML, к нему написан Restful web service, использую веб сервер WildFly 11, и проблема заключается в том, что...

201