Язык программирования C++ |
Распределение памяти
Автоматические переменные
Самый простой метод – это объявление переменных внутри функций. Если переменная объявлена внутри функции, каждый раз, когда функция вызывается, под переменную автоматически отводится память. Когда функция завершается, память, занимаемая переменными, освобождается. Такие переменные называют автоматическими .
При создании автоматических переменных они никак не инициализируются, т.е. значение автоматической переменной сразу после ее создания не определено, и нельзя предсказать, каким будет это значение. Соответственно, перед использованием автоматических переменных необходимо либо явно инициализировать их, либо присвоить им какое-либо значение.
int funct() { double f; // значение f не определено f = 1.2; // теперь значение f определено // явная инициализация автоматической // переменной bool result = true; . . . }
Аналогично автоматические переменные, объявленные внутри блока (последовательности операторов, заключенных в фигурные скобки) создаются при входе в блок и уничтожаются при выходе из блока.
Замечание. Распространенной ошибкой является использование адреса автоматической переменной после выхода из функции. Конструкция типа:
int* func() { int x; . . . return &х; }
дает непредсказуемый результат.
Статические переменные
Другой способ выделения памяти – статический
Если переменная определена вне функции, память для нее отводится статически, один раз в начале выполнения программы, и переменная уничтожается только тогда, когда выполнение программы завершается. Можно статически выделить память и под переменную, определенную внутри функции или блока. Для этого нужно использовать ключевое слово static в его определении:
double globalMax; // переменная определена вне функции void func(int x) { static bool visited = false; if (!visited) { . . . // инициализация visited = true; } . . . }
В данном примере переменная visited задается в начале выполнения программы. Ее начальное значение – false. При первом вызове функции func условие в операторе if будет истинным, выполнится инициализация, и переменной visited будет присвоено значение true. Поскольку статическая переменная создается только один раз, ее значения между вызовами функции сохраняются. При втором и последующих вызовах функции func инициализация производиться не будет.
Если бы переменная visited не была объявлена static, то инициализация происходила бы при каждом вызове функции.
Динамическое выделение памяти
Третий способ выделения памяти в языке Си++ – динамический. Память для величины какого-либо типа можно выделить, выполнив операцию new. В качестве операнда выступает название типа, а результатом является адрес выделенной памяти.
long* lp; // создать новое целое число lp = new long; Complex* cp; // создать новый объект типа Complex cp = new Complex;
Созданный таким образом объект существует до тех пор, пока память не будет явно освобождена с помощью операции delete. В качестве операнда delete должен быть задан адрес, возвращенный операцией new:
delete lp; delete cp;
Динамическое распределение памяти используется, прежде всего, тогда, когда заранее неизвестно, сколько объектов понадобится в программе и понадобятся ли они вообще. С помощью динамического распределения памяти можно гибко управлять временем жизни объектов, например выделить память не в самом начале программы (как для глобальных переменных), но, тем не менее, сохранять нужные данные в этой памяти до конца программы.
Если необходимо динамически создать массив, то нужно использовать немного другую форму new:
new int[100];
В отличие от определения переменной типа массив, размер массива в операции new может быть произвольным, в том числе вычисляемым в ходе выполнения программы. (Напомним, что при объявлении переменной типа массив размер массива должен быть константой.)
Освобождение памяти, выделенной под массив, должно быть выполнено с помощью следующей операции delete
delete [] address;