Особенности освобождения памяти в объектах, использующих, динамическую память. Использование деструкторов
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Напомним, что для эффективной организации вычислительного процесса память, выделенная динамически во время исполнения программы, должна также во время исполнения программы возвращена в систему.

Для освобождения памяти, выделенной по оператору new, используется оператор delete, который имеет следующий формат:

delete указатель

или

delete [] указатель /* для массива */

 

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

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

Напомним, что при выходе из функции производится автоматическое освобождение памяти, занятой локальными данными, в том числе и объектами.

Но в случае объектов могут быть рассмотрены две ситуации;

1-ая ситуация

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

2-ая ситуация

В функции используется локальный указатель на динамически создаваемый локальный объект. Этот объект также использует динамическую память для членов-данных. При завершении функции автоматически освобождается память, занимаемая указателем динамически созданного локального объекта. Но при этом автоматического освобождения динамической памяти как объекта, так и внутри объекта не выполняется.

Следовательно, после завершения работы функции память, используемая при работе с объектами, не может быть повторно использоваться в системе. Поэтому необходимо выполнить какие-то функции, которые выполняют действия по освобождению динамической памяти внутри объекта. Необходимо, чтобы эти функции вызывались перед завершением работы функций, использующие объекты.

В Си++ используется специальная функция, которая автоматически подключается при завершении работы с объектом. Эта функция называется деструктором. Эта функция должна быть аналогично конструктору быть описана в классе.


Формат описания деструктора

Class m1

{ int m;

……..

public:

~ m1() // заголовок деструктора

{ cout<<”rabotaet destructor<<endl;}

……………

}

В деструкторах могут быть записаны любые последовательности операторов. Обязательным оператором должен быть оператор delete для освобождения памяти, полученной динамически внутри объекта. Иначе вызов этого деструктора будет бессмысленным.

Правила, которые определяют условия автоматического вызова деструктора.

- для всех локальных объектов перед завершением работы функции;

- при выполнении операции delete над динамически созданным объектом.

- Если объект был создан динамически, то деструктор для этого объекта автоматически не вызывается.

Пример

#include<stdio.h>

#include<string.h>

#include<conio.h>

#include<iostream.h>

class q1

{ int k; /* указатель на динамический массив

int n; /* размер памяти */

int n1;/*личный номер объекта*/

public:

static int s; // текущее количество объектов

q1(int n=4) /* конструктор*/

{ k=new int[this->n=n]; // запрос памяти под динамический массив из n элементов

s++; n1=s; // формирование личного номера объекта

cout<<"личный номер "<<n1<<endl; }

~q1() // деструктор –освобождение памяти

{ delete [] k; // освобождение памяти массива целых чисел

cout<<"личный номер "<<n1<<endl;

}

 }; // конец определения класса

 void f1()

 { clrscr();

q1 obj1; // определение объекта с массивом из 4-х элементов

q1 *obj2=new q1[4]; // определение массива из 4-х объектов

delete [] obj2; // освобождение памяти массива объектов

}

int q1::s=0; /* статическая величина- текущее количество инициализированных объектов */

int main()

 {

clrscr();

f1(); // вызов функции, в которой используются объекты//

getche();

return 0;

}

 

Замечание.

1. Данный пример показывает, каким образом вызывается деструктор при завершении выполнения функции f1;

2. Сначала автоматически вызывается 4 раза деструктор при выполнении оператора delete [] obj2 – удаляется память для каждого элемента массива obj2; О порядке вызова можно судить о номере элемента объекта, так как деструктор выдает и личный номер объекта.

3. При выходе из функции f1 деструктор автоматически вызывается для объекта obj1 . Об этом также можно судить по выдаваемому личному номеру объекта.

4. Если не выполнить оператор delete obj2 , то указатель obj2 будет освобожден (как локальная переменная), но деструктор для массива объектов не будет вызван, а, следовательно, деструктор будет вызван только 1 раз, а именно для obj1.

5. Если вместо оператора delete [] obj2 записать оператор delete obj2, то в этом случае удаляется только один элемент массива obj2, на который указывает указатель obj2.

 


Перегрузка операторов

Дата: 2019-03-05, просмотров: 223.