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

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

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

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

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)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
05.10.2016, 19:45
Ответы с готовыми решениями:

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

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

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

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

Решение

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

P.S. В чем смысл метода void Matrix::get(int i, int j), который ничего не делает - не ясно.
1
0 / 0 / 0
Регистрация: 22.11.2015
Сообщений: 21
05.10.2016, 22:28  [ТС]
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Эксперт С++
 Аватар для TheCalligrapher
12931 / 6799 / 1820
Регистрация: 18.10.2014
Сообщений: 17,210
05.10.2016, 23:07
Цитата Сообщение от Ilya2016 Посмотреть сообщение
Что в это раз не так?
В операторе присваивания памяти выделяется недостаточно. Судя по конструктору Matrix:Matrix() вы сами знаете, что выделять массив надо размера dimension*dimension, а вы в операторе присваивания выделяете только dimension. Та же проблема с конструктором копирования. Может надо как-то самому учиться отлавливать такие "детские" баги?

И теперь вы зачем-то искорежили свой оператор +. В первой версии было все нормально (по крайней мере внешне), а теперь вы из оператора + вдруг ни стого ни с сего сделали некое подобие оператора +=. Зачем? Почему?
1
0 / 0 / 0
Регистрация: 22.11.2015
Сообщений: 21
05.10.2016, 23:47  [ТС]
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Эксперт С++
 Аватар для TheCalligrapher
12931 / 6799 / 1820
Регистрация: 18.10.2014
Сообщений: 17,210
06.10.2016, 00:04
Цитата Сообщение от Ilya2016 Посмотреть сообщение
вызывается деструктор для this и удаляет temp
Мне трудно представить, о чем идет речь, не видя финальной версии кода, в т.ч. вызывающего кода. Как выглядит код?
0
0 / 0 / 0
Регистрация: 22.11.2015
Сообщений: 21
06.10.2016, 00:05  [ТС]
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Эксперт С++
 Аватар для TheCalligrapher
12931 / 6799 / 1820
Регистрация: 18.10.2014
Сообщений: 17,210
06.10.2016, 00:11
Никаких проблем с oldObject на входе в operator = я не вижу.

После выхода из operator + (подразумевая, что вы вернули его к прежнему виду) вызывается деструктор временного объекта - это тоже нормально. Что такое "вызывается деструктор для this" я не понял.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
06.10.2016, 00:11
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru