Джесс Либерти - Освой самостоятельно С++ за 21 день. Страница 46
- Категория: Компьютеры и Интернет / Программирование
- Автор: Джесс Либерти
- Год выпуска: неизвестен
- ISBN: нет данных
- Издательство: неизвестно
- Страниц: 170
- Добавлено: 2019-05-29 10:34:04
Джесс Либерти - Освой самостоятельно С++ за 21 день. краткое содержание
Прочтите описание перед тем, как прочитать онлайн книгу «Джесс Либерти - Освой самостоятельно С++ за 21 день.» бесплатно полную версию:В книге широко представлены возможности новейшей версии программного продукта Microsoft Visual C++. Подробно описаны средства и подходы программирования современных профессиональных приложений. Материалы книги дополнены многочисленными демонстрационными программами, в процессе разработки которых максимально используются возможности программных инструментов Microsoft Visual Studio. Особое внимание уделено новинкам версии 6.0 и новейшим технологиям объектно-ориентированного программирования, включая использование библиотеки MFC и шаблонов классов, а также создание связанных списков. Отдельное занятие посвящено вопросам объектно-ориентированного анализа и проектирования приложений. Подробно рассмотрены все средства и подходы конструирования собственных пользовательских классов.Книга рассчитана на широкий круг читателей, интересующихся современными проблемами программирования.
Джесс Либерти - Освой самостоятельно С++ за 21 день. читать онлайн бесплатно
unsigned short int theVariable = 5;
unsigned short int * pPointer = & theVariable;
Чтобы разыменовать указатель, установите перед его именем оператор разыменовывания (*):
unsigned short int theValue = *pPointer
Для чего нужны указатели
В предыдущих разделах мы детально рассмотрели процедуру присвоения указателю адреса другой переменной. Однако на практике такое использование указателей встречается достаточно редко. К тому же, зачем задействовать еще и указатель, если значение уже хранится в другой переменной? Рассмотренные выше примеры приведены только для демонстрации механизма работы указателей. Теперь, после описания синтаксиса, используемого в C++ для работы с указателями, можно переходить к более профессиональному их применению. Наиболее часто указатели применяются в следующих случаях:
• для размещения данных в свободных областях памяти и доступа к ним;
• для доступа к переменным и функциям классов;
• для передачи параметров в функции по ссылке.
Оставшаяся часть главы посвящена динамическому управлению данными и операциям с переменными и функциями классов.
Память стековая и динамически распределяемая
Если вы помните, на занятии 5 приводились условное разделение памяти на пять областей:
• область глобальных переменных;
• свободная, или динамически распределяемая память;
• регистровая память (регистры);
• сегменты программы;
• стековая память.
Локальные переменные и параметры функций размещаются в стековой памяти. Программный код хранится в сегментах, глобальные переменные — в области глобальных переменных. Регистровая память предназначена для хранения внутренних служебных данных программы, таких как адрес вершины стека или адрес команды. Остальная часть памяти составляет так называемую свободную память — область памяти, динамически распределяемую между различными объектами.
Особенностью локальных переменных является то, что после выхода из функции, в которой они были объявлены, память, выделенная для их хранения, освобождается, а значения переменных уничтожаются.
Глобальные переменные позволяют частично решить эту проблему ценой неограниченного доступа к ним из любой точки программы, что значительно усложняет восприятие текста программы. Использование динамической памяти полностью решает обе проблемы.
Чтобы понять, что же такое динамическая память, попытайтесь представить область памяти, разделенную на множество пронумерованных ячеек, в которых записана информация. В отличие от стека переменных, ячейкам свободной памяти нельзя присвоить имя. Доступ к ним осуществляется посредством указателя, хранящего адрес нужной ячейки.
Чтобы лучше понять изложенное выше, рассмотрим пример. Допустим, вам дали номер телефона службы заказов товара по почте. Придя домой, вы занесли этот номер в память вашего телефона, а листок бумаги, на котором он был записан, выбросили. Нажимая на кнопку телефона, вы соединяетесь со службой заказа. Для вас не имеет значения номер и адрес этой службы, поскольку вы уже получили доступ к интересующей вас информации. Служба заказов в данном случае является моделью динамической памяти. Вы не знаете, где именно находится нужная вам информация, но знаете, как ее получить. Для обращения к значению используется его адрес, роль которого играет телефонный номер. Причем помнить адрес (или номер) не обязательно — достаточно лишь записать его значение в указатель (или телефон). После этого, используя указатель, можно извлечь нужное значение, даже не зная место его расположения.
Что касается стека переменных, то по завершении работы функции он очищается. В результате все локальные переменные оказываются вне области видимости и их значения уничтожаются. В отличие от стека, динамическая память не очищается до завершения работы программы, поэтому в таком случае освобождением памяти должен заниматься программист.
Важным преимуществом динамической памяти является то, что выделенная в ней облаять памяти не может использоваться до тех пор, пока явно не будет освобождена. Поэтому, если память в динамической области выделяется во время работы функции, ее можно будет использовать даже после завершения работы.
Еще одним преимуществом динамического выделения памяти перед использованием глобальных переменных является то, что доступ к данным можно получить только из функций, в которых есть доступ к указателю, хранящему нужный адрес. Такой способ доступа позволяет жестко контролировать характер манипулирования данными, а также избегать нежелательного или случайного их изменения.
Для работы с данными описанным способом прежде всего нужно создать указатель на ячейки динамической области памяти. О том, как это сделать, читайте в следующем разделе.
Оператор new
Для выделения памяти в области динамического распределения используется ключевое слово new. После new следует указать тип объекта, который будет размещаться в памяти. Это необходимо для определения размера области памяти, требуемой для хранения объекта. Написав, например, new unsigned short int, мы выделим два байта памяти, а строка new long динамически выделит четыре байта.
В качестве результата оператор new возвращает адрес выделенного фрагмента памяти. Этот адрес должен присваиваться указателю. Например, для выделения памяти в области динамического обмена переменной типа unsigned short можно использовать такую запись:
unsigned short int * pPointer; pPointer = new unsigned short int;
Или выполнить те же действия, но в одной сороке:
unsigned short int * pPointer = new unsigned short int;
В каждом случае указатель pPointer будет указывать на ячейку памяти в области динамического обмена, содержащую значение типа unsigned short. Теперь pPointer можно использовать как любой другой указатель на переменную этого типа. Чтобы занести в выделенную область памяти какое-нибудь значение, напишите такую строку:
*pPointer = 72;
Эта строка означает следующее: "записать число 72 в память по адресу, хранящемуся в pPointer".
Ввиду того что память является ограниченным ресурсом, попытка выделения памяти оператором new может оказаться неудачной. В этом случае возникнет исключительная ситуация, которая рассматривается на занятии 20.
Оператор delete
Когда память, выделенная под переменную, больше не нужна, ее следует освободить. Делается это с помощью оператора delete, после которого записывается имя указателя. Оператор delete освобождает область памяти, определенную указателем. Необходимо помнить, что указатель, в отличие от области памяти, на которую он указывает, является локальной переменной. Поэтому после выхода из функции, в которой он был объявлен, этот указатель станет недоступным. Однако область памяти, выделенная оператором new, на которую сослался указатель, при этом не освобождается. В результате часть памяти окажется недоступной. Программисты называют такую ситуацию утечкой памяти. Такое название полностью соответствует действительности, поскольку до завершения работы программы эту память использовать нельзя, она как бы "вытекает" из вашего компьютера.
Чтобы освободить выделенную память, используйте ключевое слово delete, например:
delete pPointer;
На самом деле при этом происходит не удаление указателя, а освобождение области памяти по адресу, записанному в нем. При освобождении выделенной памяти с самим указателем ничего не происходит и ему можно присвоить другой адрес. Листинг 8.4 показывает, как выделить память для динамической переменной, использовать ее, а затем освободить.
Предупреждение:Когда оператор delete применяется к указателю, происходит освобождение области динамической памяти, на которую этот указатель ссылается. Повторное применение оператора delete к этому же указателю приведет к зависанию программы. Рекомендуется при освобождении области динамической памяти присваивать связанному с ней указателю нулевое значение. Вызов оператора delete для нулевого указателя пройдет совершенно безболезненно для программы, например:
Animal *pDog = new Animal;
delete pDog; // освобождение динамической памяти
pDog = 0 // присвоение указателю нулевого значения
// ...
delete pDog; // бессмысленная, но совершенно безвредная строка
Листинг 8.4. Выделение, использование и освобождение динамической памяти
1; // Листинг 8, 4,
2; // Выделение, использование и освобождение динамической памяти 3;
4: #include <iostream.h>
Жалоба
Напишите нам, и мы в срочном порядке примем меры.