С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/15: Рейтинг темы: голосов - 15, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 22.11.2015
Сообщений: 21
1

Освобождение памяти динамического массива. Деструктор

05.10.2016, 19:45. Показов 2791. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Почему выдает ошибку при написании деструктора? Если его убрать, то все работает.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#pragma once
 
#ifndef MATRIX_H
 
#define MATRIX_H
 
#include <ctime>
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
class Matrix
{
    int dimension;
    double * pointer;
public:  int counter = 0; // Для подсчета количества созданных объектов
 
public:
    Matrix(int dim = 2) {
        
        counter++;
        dimension = dim;
        pointer = new double[dim*dim];
        srand(time(NULL)); // инициализация функции rand значением функции time
        for (int i = 0; i < dim*dim; i++)
            pointer[i] = rand() % 14 + 5;
    }
    Matrix(const Matrix&);
    void point();
    ~Matrix() { delete []pointer; }
 
    void get(int, int);
    void set(int, int, double);
    Matrix operator+(const Matrix&);
    
};
 
#endif // !MATRIX_H
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include"Matrix.h"
 
//Matrix::Matrix
 
void Matrix::point() {
    for(int i = 0; i < dimension; i++)
    {
        for(int j = 0; j < dimension; j++)
            cout << pointer[i*dimension + j] << "   ";
        cout << endl;
    }
    
}
 
Matrix::Matrix(const Matrix& oldObject) {
    dimension = oldObject.dimension;
 
    pointer = new double[dimension*dimension];
    for (int i = 0; i < dimension; i++)
        for (int j = 0; j < dimension; j++)
            pointer[i*dimension + j] = oldObject.pointer[i*dimension + j];
    
 
}
 
 
 
void Matrix::get(int i, int j) {
    if (i > dimension || i<0 || j>dimension || j < 0)
        cout << "Столбец или строчка введена неверно";
    else cout << pointer[i*dimension + j] << "/t";
}
void Matrix::set(int i, int j, double element) {
    if (i > dimension || i<0 || j>dimension || j < 0)
        cout << "Столбец или строчка введена неверно";
    else pointer[i*dimension + j] = element;
}
 
Matrix Matrix::operator+(const Matrix& M2) {
    Matrix temp(*this);
    for (int i = 0; i < dimension; i++)
    {
        for (int j = 0; j < dimension; j++)
        {
            temp.pointer[i*dimension + j] += M2.pointer[i*dimension + j];
        }
    }
    return temp;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include"Matrix.h"
 
int main() {
    Matrix mat;
    Matrix mat1;
    Matrix mat2;
    
    mat2.point();
    mat2 = mat + mat1;
    //Matrix mat1(mat);
    mat2.point();
    
    
    return 0;
}
Миниатюры
Освобождение памяти динамического массива. Деструктор  
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.10.2016, 19:45
Ответы с готовыми решениями:

Освобождение памяти у динамического массива char
Добрый день. Имеем код: class _ArrayChar { typedef int Ivalue; typedef char* Pchar;...

Освобождение памяти динамического массива структур
Поставлена следующая задача: сделать любую структуру, сгененировать в неё рандомные данные,...

Освобождение памяти после динамического массива
Есть динамический массив, но почему-то на строке delete FirstPoint; студия (2010) пишет что-то про...

Деструктор: освобождение памяти
Как в этом случае освободить память, запутался помогите пожалуйста. class TClass { public: int...

8
59 / 59 / 53
Регистрация: 05.05.2013
Сообщений: 150
05.10.2016, 20:07 2
Лучший ответ Сообщение было отмечено Ilya2016 как решение

Решение

При копировании экземпляров класса с динамически выделенной памятью необходимо явно определить конструктор копирования и оператор =
У вас фактически происходит двойное освобождение выделенной памяти, т. к. конструктор копирования по умолчанию осуществляет поверхностное копирование
1
Вездепух
Эксперт CЭксперт С++
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
05.10.2016, 20:12 3
Цитата Сообщение от Ilya2016 Посмотреть сообщение
Почему выдает ошибку при написании деструктора?
Нарушено Правило Трех: отсутствует корректно реализованный копирующий оператор присваивания. Конструктор копирования есть, деструктор есть, а оператора присваивания нет. А в программе он используется...

P.S. В чем смысл метода void Matrix::get(int i, int j), который ничего не делает - не ясно.
1
0 / 0 / 0
Регистрация: 22.11.2015
Сообщений: 21
05.10.2016, 22:28  [ТС] 4
VAN0, TheCalligrapher, Изменил. Что в это раз не так?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#pragma once
 
#ifndef MATRIX_H
 
#define MATRIX_H
 
#include <ctime>
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
class Matrix
{
    int dimension;
    double * pointer;
public:  int counter = 0; // Для подсчета количества созданных объектов
 
public:
    Matrix(int dim = 2) {
        
        counter++;
        dimension = dim;
        pointer = new double[dim*dim];
        srand(time(NULL)); // инициализация функции rand значением функции time
        for (int i = 0; i < dim*dim; i++)
            pointer[i] = rand() % 14 + 5;
 
 
 
    
    }
    Matrix (const Matrix&);
    void point();
    ~Matrix() { delete []pointer; cout << "Деструктор" << endl;}
 
    void get(int, int);
    void set(int, int, double);
    Matrix& operator+(const Matrix&);
    Matrix& operator=(const Matrix&);
 
    //Matrix operator*(const Matrix&);
    
    // ---- Конструктор инициализации ( случайные числа от 5 до 14 включительно ) +
    // ---- Копирующий конструктор +
    // ---- Все конструкторы должны содержать код обеспечивающий корректную        // работу со счетчиком класса при создании нового объекта как на стеке так и в    // динамической памяти
    // ---- Деструктор ( работа с памятью + корректировка счетчика перед уничтожением +
    //       объекта
    // ---- Функция для получения значений матрицы +
    // ---- Функция для задания значений отдельным ячейкам матрицы +
    // ---- Форматированная печать матрицы +
    // ---- Функция для сложения двух матриц  ( перегруженная операторная функция)
    // ---- Функция умножения матрицы на число ( перегруженная операторная функция)
    // ---- Статическая функция класса для работы со статическим атрибутом
};
 
#endif // !MATRIX_H
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include"Matrix.h"
 
//Matrix::Matrix
 
void Matrix::point() {
    for(int i = 0; i < dimension; i++)
    {
        for(int j = 0; j < dimension; j++)
            cout << pointer[i*dimension + j] << "   ";
        cout << endl;
    }
    
}
 
Matrix::Matrix(const Matrix& oldObject) {
    cout << "Конструктор копирования" << endl;
    dimension = oldObject.dimension;
    pointer = new double[dimension];
    for (int i = 0; i < dimension; i++)
        for (int j = 0; j < dimension; j++)
            pointer[i*dimension + j] = oldObject.pointer[i*dimension + j];
}
 
Matrix& Matrix::operator=(const Matrix& oldObject) {
    if (this != &oldObject)
    {
        cout << "Перегруженный оператор присваивания" << endl;
        delete[]pointer;
        dimension = oldObject.dimension;
        pointer = new double[dimension];
        for (int i = 0; i < dimension; i++)
            for (int j = 0; j < dimension; j++)
                pointer[i*dimension + j] = oldObject.pointer[i*dimension + j];
    }
    else cout << "Самоприсваивание" << endl;
    return *this;
}
 
void Matrix::get(int i, int j) {
    if (i > dimension || i<0 || j>dimension || j < 0)
        cout << "Столбец или строчка введена неверно";
    else cout << pointer[i*dimension + j] << "/t";
}
void Matrix::set(int i, int j, double element) {
    if (i > dimension || i<0 || j>dimension || j < 0)
        cout << "Столбец или строчка введена неверно";
    else pointer[i*dimension + j] = element;
}
 
Matrix& Matrix::operator+(const Matrix& M2) {
    //Matrix temp(*this);
    for (int i = 0; i < dimension; i++)
    {
        for (int j = 0; j < dimension; j++)
        {
            pointer[i*dimension + j] += M2.pointer[i*dimension + j];
        }
    }
    return *this;
}
    
 
/*Matrix Matrix::operator*(const Matrix& M2) {
 
    Matrix temp(*this);
    for (int i = 0; i < dimension; i++) {
        for (int j = 0; j < dimension; j++) {
            temp.pointer[i*dimension + j] = 0;
            for (int k = 0; k < dimension; k++)
                temp.pointer[i*dimension + j] += pointer[i*dimension + k] * M2.pointer[k*dimension + j];
 
 
        }
 
 
    }
    
 
    return temp;
}*/
0
Вездепух
Эксперт CЭксперт С++
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
05.10.2016, 23:07 5
Цитата Сообщение от Ilya2016 Посмотреть сообщение
Что в это раз не так?
В операторе присваивания памяти выделяется недостаточно. Судя по конструктору Matrix:Matrix() вы сами знаете, что выделять массив надо размера dimension*dimension, а вы в операторе присваивания выделяете только dimension. Та же проблема с конструктором копирования. Может надо как-то самому учиться отлавливать такие "детские" баги?

И теперь вы зачем-то искорежили свой оператор +. В первой версии было все нормально (по крайней мере внешне), а теперь вы из оператора + вдруг ни стого ни с сего сделали некое подобие оператора +=. Зачем? Почему?
1
0 / 0 / 0
Регистрация: 22.11.2015
Сообщений: 21
05.10.2016, 23:47  [ТС] 6
TheCalligrapher, Почему-то в функцию
C++
1
Matrix& Matrix::operator=(const Matrix& oldObject) {
oldObject передается со значением 0x00bdfda8 {dimension=-858993460 pointer=0xcccccccc {???} counter=-858993460 } Ив роде бы после
C++
1
2
3
4
5
6
7
8
9
10
11
Matrix Matrix::operator+(const Matrix& M2) {
    Matrix temp(*this);
    for (int i = 0; i < dimension; i++)
    {
        for (int j = 0; j < dimension; j++)
        {
            temp.pointer[i*dimension + j] += M2.pointer[i*dimension + j];
        }
    }
    return temp;
}
вызывается деструктор для this и удаляет temp
0
Вездепух
Эксперт CЭксперт С++
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
06.10.2016, 00:04 7
Цитата Сообщение от Ilya2016 Посмотреть сообщение
вызывается деструктор для this и удаляет temp
Мне трудно представить, о чем идет речь, не видя финальной версии кода, в т.ч. вызывающего кода. Как выглядит код?
0
0 / 0 / 0
Регистрация: 22.11.2015
Сообщений: 21
06.10.2016, 00:05  [ТС] 8
TheCalligrapher,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include"Matrix.h"
 
int main() {
    Matrix mat;
    Matrix mat1;
    Matrix mat2;
    
    mat2.point();
    mat2 = mat + mat1;
    //Matrix mat1(mat);
    mat2.point();
    
    
    return 0;
}
0
Вездепух
Эксперт CЭксперт С++
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
06.10.2016, 00:11 9
Никаких проблем с oldObject на входе в operator = я не вижу.

После выхода из operator + (подразумевая, что вы вернули его к прежнему виду) вызывается деструктор временного объекта - это тоже нормально. Что такое "вызывается деструктор для this" я не понял.
0
06.10.2016, 00:11
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.10.2016, 00:11
Помогаю со студенческими работами здесь

Освобождение памяти для динамического масива типа char
Здравствуйте, помогите пожалуйста разобраться с одним моментом. При освобождении памяти двумерного...

Освобождение динамического двумерного массива указателей
Доброго времени суток. Подскажите как правильно очистить память после вот такого выделения: ...

Резервирование памяти/освобождение памяти для трехмерного массива
Необходимо создать трехмерный массив (A), в котором элементы вдоль направления Z выли бы выровнены...

Динамическая загрузка и освобождение памяти для двумерного массива
Всем добрый день:victory: У меня возник небольшой вопрос , и надеюсь что отзывчивые форумчане 8-)...

Освобождение памяти (удаление массива char) и raised exception class EAccessViolation
Подскажите плиз, есть программа, вот кусок AnsiString inputText; int inputTextLength;...

Как правильно записать в виде функции выделение памяти для двумерного массива и ее освобождение
Здравствуйте! Подскажите, как правильно записать в виде функции выделение памяти для двумерного...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru