Программирование >>  Дополнительные возможности наследования 

1 ... 61 62 63 [ 64 ] 65 66 67 ... 265


в строке 8 объявляются две переменные типа unsigned short - myAge и yourAge. Далее, в строке 9, объявляется указатель на этот тип (рАде). Этому указателю присваивается адрес переменной myAge.

В строках 10 и 11 значения и адреса переменных рАде и myAge выводятся на экран. Обращение к значению переменной myAge путем разыменования указателя рАде выполняется в строке 13. Перед тем как перейти к дальнейшему изучению материала, подумайте, все ли вам понятно в рассмотренном примере. Еще раз проанализируйте текст программы и результат ее выполнения.

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

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

Рекоменддется

Используйте оператор разыменовывания (.) для получения доступа к данным, сохраненным по адресу, содержащемуся в указателе.

Инициализируйте указатель нулевым значением при объявлении, если заранее не известно, для указания на какую переменную он будет использоваться.

Рекомендуется

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

Использование дказателе!

Чтобы объявить указатель, запишите вначале тип переменной или объекта, на который будет ссылаться этот указатель, затем поместите символ звездочки (*), а за ним - имя нового указателя, например:

unsigned short int pPointer =0;

Чтобы присвоить указателю адрес переменной, установите перед именем переменной оператор адреса (&), как в следующем примере:

unsigned short int theVariable = 5; ; :,j.ri-~

unsigned short int * pPointer = & theVariable;

Чтобы разыменовать указатель, установите перед его именем оператор разыменовывания (*):

unsigned short int theValue = *pPointer :



Для чего нужны указатели

в предыдущих разделах мы детально рассмотрели процедуру присвоения указателю адреса другой переменной. Однако на практике такое использование указателей встречается достаточно редко. К тому же, зачем задействовать еще и указатель, если значение уже хранится в другой переменной? Рассмотренные выще примеры приведены только для демонстрации механизма работы указателей. Теперь, после описания синтаксиса, используемого в С++ для работы с указателями, можно переходить к более профессиональному их применению. Наиболее часто указатели применяются в следующих случаях:

для размещения данных в свободных областях памяти и доступа к ним;

для доступа к переменным и функциям классов;

для передачи параметров в функции по ссылке.

Оставшаяся часть главы посвящена динамическому управлению данными и операциям с переменными и функциями классов.

Память стековая и уинамически распреуеляемая

Если вы помните, на занятии 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;



1 ... 61 62 63 [ 64 ] 65 66 67 ... 265

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика