Резервирование и освобождение памяти (операторы new и delete)
Основное назначение указателей состоит в обеспечении возможности работы с динамическими (создаваемыми в процессе выполнения программы) переменными встроенных и производных типов. При такой работе указатели используются как средство хранения адресов резервируемых и освобождаемых участков памяти. Сами же действия, связанные с резервированием и освобождением памяти, осуществляют операторы new и delete.
Оператор new резервирует в области динамической памяти запрошенный участок памяти и возвращает его адрес, а оператор delete освобождает зарезервированный ранее участок памяти. Возможный формат этих операторов:
идентификатор = new тип ;
delete идентификатор ;
Здесь идентификатор – имя указателя, получающего в качестве значения адрес выделенной памяти, достаточной для размещения данных указанного типа. Пример:
int *ip; // указатель на целое значение типа int
...
ip = new int; // резервирование памяти для целого числа
...
delete ip; // освобождение памяти, адресуемой указателем ip
После выполнения последнего оператора примера память, выделенная для переменной типа int и адресуемая указателем ip, становится свободной (недоступной для использования, но доступной для нового резервирования оператором new). Переменная-указатель ip по-прежнему может использоваться в программе, но в текущий момент времени его значение становится неопределенным, указывающим на недоступный участок памяти.
Объявление указателя и резервирование памяти можно объединить:
int *ip = new int; // объявление и инициализация указателя на целое число
Приведенное объявление инициализирует переменную-указатель ip адресом выделенного ей участка памяти для переменной типа int, при этом значение данного участка памяти не определено. Существует возможность применения оператора new с инициализацией выделяемого участка памяти соответствующим значением. Формат оператора new при такой инициализации:
идентификатор = new тип ( значение );
например:
int *ip = new int(10); // выделение участка памяти для целого числа
// и его инициализация значением 10
Последний оператор объявляет переменную-указатель ip, резервирует требуемый участок памяти, присваивает этот адрес объявленной переменной и записывает по данному адресу начальное значение 10.
Для резервирования памяти для одномерного массива следует использовать оператор new формата
идентификатор = new тип [ размер ]
а для его освобождения – оператор delete формата
delete [] идентификатор ;
например:
int *p = new int[5]; // выделение памяти для массива из пяти целых чисел
...
delete []p; // освобождение памяти, зарезервированной для массива p
Наличие квадратных скобок указывает на необходимость освобождения памяти, занимаемой массивом, а не одной переменной.
Размер участка памяти, выделяемой для одномерного массива, может задаваться как целочисленным константным выражением, так и выражением, содержащим переменные, например:
int n;
...
cin >> n;
int *p = new int[n]; // выделение памяти для массива из n целых чисел
Инициализация элементов массива, определяемого посредством оператора new, в C++ не предусмотрена.
Не следует забывать о различиях в использовании квадратных и круглых скобок при работе с динамической памятью. Так, оператор:
int *p = new int[n];
осуществляет выделение памяти для массива из n целых чисел, а похожий оператор
int *p = new int(n);
– выделение памяти для одной переменной целого типа с начальным значением n.
С помощью оператора newможно выделять память и для многомерных (в частности, двумерных) массивов и массивов указателей.
Для освобождения памяти, динамически (с помощью оператора new) выделенной под двумерный массив a, следует использовать тот же, что и для одномерного массива, оператор
delete []a;
Поскольку при создании динамических массивов всего одна размерность может быть переменной, использование динамических двумерных массивов целесообразно, когда их необходимость заранее неизвестна и зависит от каких-то внешних условий.
Следует подчеркнуть, что динамически (с помощью оператора delete) можно освободить только ту память, которая была динамически (с помощью оператора new) получена.