Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Материалы(С++).doc
Скачиваний:
6
Добавлен:
17.11.2019
Размер:
385.54 Кб
Скачать

Динамически распределяемая память

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

Реально указатели применяются в следующих случаях:

  • управление данными в свободной (динамической) области памяти;

  • передача данных между функциями по ссылке.

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

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

Ячейкам свободной памяти нельзя присвоить имя, можно лишь зарезервировать определенное количество ячеек и запомнить их адрес в указателе. С помощью указателей и осуществляется доступ к участкам динамической памяти.

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

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

указатель = new выражение;

Аргументом для оператора new служит выражение, возвращающее число байтов, которые необходимо зарезервировать в области динамической памяти.

Например, чтобы создать в динамической памяти переменную типа unsigned short необходимо записать:

unsigned short int *ptr = new unsigned short int;

  1. Выражение new unsigned short int выделяет два байта динамической памяти.

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

  1. Кроме того, ptr указывает на переменную типа unsigned short int, размещенную в динамически распределяемой памяти. Строку

*ptr = 21;

можно прочитать: «разместить число 21 в той области динамически распределяемой памяти, на которую указывает ptr».

По завершении работы с выделенной областью памяти ее следует освободить. Сама она не освобождается автоматически при выходе из функции и остается занятой, а программа не сможет ею воспользоваться. Если функция часто вызывается, памяти будет оставаться все меньше и наступит момент, когда ее не останется вовсе, и программа аварийно завершиться. Чтобы этого не произошло, когда необходимость в выделенном участке памяти отпадает, его надо освободить используя оператор delete:

delete указатель;

Здесь указатель содержит адрес участка памяти, ранее выделенный с помощью операции new.

Например,

delete p;

где p ранее объявлен как указатель.

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

Когда оператор delete применяется к указателю, происходит освобождение области динамической памяти, на которую этот указатель ссылается. Повторное применение оператора delete к этому же указателю приведет к зависанию программы. Рекомендуется при освобождении области динамической памяти присваивать связанному с ней указателю нулевое значение (0 либо NULL) – вызов оператора delete для нулевого указателя не приведет к описанной выше проблеме.

Ниже приведен пример создания и удаления указателей.

//Пример_9

#include <iostream>

using namespace std;

int main()

{

int Var = 7; // объявление и инициализация переменной Var

int *ptrVar =&Var; // объявление указателя и присвоение ему адреса

int *ptrHeap=new int; // объявлен еще один указатель, а в динамической

// памяти выделено пространство для переменной типа int

*ptrHeap=21; // участку динамической памяти присвоено значение

cout<<"Value Var: "<<Var<<endl; // вывод содержимого переменной Var

cout<<"Value *ptrVar: "<<*ptrVar<<endl; // вывод значения,

//на которое указывает ptrVar

cout<<"Value *ptrHeap: "<<*ptrHeap<<endl; // вывод значения, на

// которое указывает ptrHeap

delete ptrHeap; // освобождение участка динамической памяти,

// указатель ptrHeap пуст и пригоден для записи

// адреса другого участка памяти

ptrHeap = new int; // в динамической памяти вновь выделено

// пространство для переменной типа int

*ptrHeap=3; // участку динамической памяти присвоено новое значение

cout<<"Value *ptrHeap: "<<*ptrHeap<<endl; // вывод значения, на

// которое указывает ptrHeap

delete ptrHeap; // освобождение участка динамической памяти

return 0;

}