|
Программирование >> Дополнительные возможности наследования
Эта строка означает следующее: записать число 72 в память по адресу, хранящемуся в pPointer . Ввиду того что память является ограниченным ресурсом, попытка выделения памяти оператором new может оказаться неудачной. В этом случае возникнет исключительная ситуация, которая рассматривается на занятии 20. Оператор delete Когда память, вьщеленная под переменную, больше не нужна, ее следует освободить. Делается это с помощью оператора delete, после которого записывается имя указателя. Оператор delete освобождает область памяти, определенную указателем. Необходимо помнить, что указатель, в отличие от области памяти, на которую он указывает, является локальной переменной. Поэтому после выхода из функции, в которой он был обьявлен, этот указатель станет недоступным. Однако область памяти, вьщеленная оператором new, на которую сослался указатель, при этом не освобождается. В результате часть памяти окажется недоступной. Программисты называют такую ситуацию утечкой памяти. Такое название полностью соответствует действительности, поскольку до завершения работы программы эту память использовать нельзя, она как бы вытекает из вашего компьютера. Чтобы освободить вьщеленную память, используйте ключевое слово delete, например: delete pPointer; На самом деле при этом происходит не удаление указателя, а освобождение области памяти по адресу, записанному в нем. При освобождении выделенной памяти с самим указателем ничего не происходит и ему можно присвоить другой адрес. Листинг 8.4 показывает, как выделить память для динамической переменной, использовать ее, а затем освободить. Когда оператор delete применяется к указателю, происходит освобождение области динамической памяти, на которую этот указатель ссылается. Повторное применение оператора delete к этому же указателю приведет к зависанию программы. Рекомендуется при освобождении области динамической памяти присваивать связанному с ней указателю нулевое значение. Вызов оператора delete для нулевого указателя пройдет совершенно безболезненно для программы, например: Animal рОод = new Animal; delete pDog; освобождение динамической памяти pDog = О присвоение указателю нулевого значения ... delete pDog; бессмысленная, но совершенно безвредная строка Днсшннв 8.4. ВыдежЕнив, испожьзрввннв н РсвоОРЖАЕнив АинвмнчвсквР пвмяшн Листинг 8,4. Выделение, использование и освобождение динамической памяти Sinclude <lostroam,h> Int mainO 7. int localVariable = 5; 8: int * pLocal= &localVariable; 9: int * pHeap = new int; 10: .pHeap = 7; 11: cout localVariable: localVariable \ n 12. cout << *pLocal: << *pLocal << \ n ; 13: cout *pHeap: *pHeap \ n ; 14: delete pHeap; 15: pHcap = new int; 16: .pHeap = 9; 17: cout << *pHeap: << *pHeap << \ n ; 18: delete pHeap; 19: return 0; 20: } localVariable: 5 *pLocal: 5 .pHeap: 7 *pHeap: 9 В строке 7 объявляется и инициализируется локальная переменная localVariable. Затем объявляется указатель, которому присваивается адрес этой переменной (строка 8). В строке 9 выделяется память для переменной типа int и адрес выделенной области помещается в указатель рНеар. Записав по адресу, содержащемуся в рНеар, значение 7, можно удостовериться в том, что память была выделена корректно (строка 10). Если бы память под переменную не была выделена, то при выполнении этой строки появилось бы сообщение об ошибке. Чтобы не перегружать примеры излишней информацией, мы опускаем всякого рода проверки. Однако во избежание аварийного завершения программы при решении реальных задач такой контроль обязательно должен выполняться. В строке 10, после выделения памяти, по адресу в указателе записывается значение 7. Затем в строках 11 и 12 значения локальной переменной и указателя pLocal выводятся на экран. Вполне понятно, почему эти значения равны. Далее, в строке 13, выводится значение, записанное по адресу, хранящемуся в указателе рНеар. Таким образом, подтверждается, что значение, присвоенное в строке 10, действительно доступно для использования. Освобождение области динамической памяти, выделенной в строке 9, осуществляется оператором delete в строке 14. Освобожденная память становится доступной для дальнейшего использования, и ее связь с указателем разрывается. После этого указатель рНеар может использоваться для хранения нового адреса. В строках 15 и 16 выполняется повторное выделение памяти и запись значения по соответствующему адресу. Затем в строке 17 это значение выводится на экран, после чего память освобождается. Вообще говоря, строка 18 не является обязательной, так как после завершения работы программы вся выделенная в ней память автоматически освобождается. Однако явное освобождение памяти считается как бы правилом хорошего тона в программировании. Кроме того, это может оказаться полезным при редактировании программы. Что такое утечка памято При невнимательной работе с указателями может возникнуть эффект так называемой утечки памяти. Это происходит, если указателю присваивается новое значение, а память, на которую он ссылался, не освобождается. Ниже показан пример такой ситуации. unsigned short int * pPointer = new unsigned short int; ♦pPointer = 72; pPointer = new unsigned short int; pPointer = 84; В строке I обьявляется указатель и выделяется память для хранения переменной типа unsigned short int. В следующей строке в вьщеленную область записывается значение 72. Затем в строке 3 указателю присваивается адрес другой области памяти, в которую записывается число 84 (строка 4). После выполнения таких операций память, содержащая значение 72, оказывается недоступной, поскольку указателю на эту область было присвоено новое значение. В результате невозможно ни использовать, ни освободить зарезервированную память до завершения программы. Правильнее было бы написать следующее: unsigned short int * pPointer = new unsigned short int; ♦pPointer = 72; delete pPointer; pPointer = new unsigned short int; ♦pPointer = 84; В этом случае память, вьщеленная под переменную, корректно освобождается (строка 3). примечание Каждый раз, когда в программе используется оператор new, за ним должен следовать оператор delete. Очень важно следить, какой указатель ссылается на выделенную область динамической памяти, и вовремя освобождать ее. Размещеное оОъектов в оОласто уонамоческо памято Аналогично созданию указателя на целочисленный тип, можно динамически размещать в памяти любые обьекты. Например, если вы объявили объект класса Cat, для манипулирования этим объектом можно создать указатель, в котором будет храниться его адрес, - ситуация, абсолютно аналогичная размещению переменных в стеке. Синтаксис этой операции такой же, как и для целочисленных типов: Cat pCat = new Cat; В данном случае использование оператора new вызывает конструктор класса по умолчанию, т.е. конструктор, использующийся без параметров. Важно помнить, что при создании объекта класса конструктор вызывается всегда, независимо от того, размещается объект в стеке или в области динамического обмена.
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |