Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
A.doc
Скачиваний:
36
Добавлен:
09.04.2015
Размер:
5.6 Mб
Скачать

198 Глава 4

Все прочие измерения должны быть заданы константами или константными вы- ражениями. Поэтому вы можете записать следующим образом:

где max — переменная; однако спецификация переменной для всех других измере- ний массива кроме крайнего левого, вызовет сообщение компилятора об ошибке.

Использование ссылок

Ссылка (reference) во многих отношениях подобна указателю — вот почему я пред- ставляю ее здесь, хотя на самом деле это совсем другая вещь. Истинная ценность ссы- лок становится ясной, только когда рассматривается их применение с функциями, в частности в контексте объектно-ориентированного программирования. Не позволяй- те ввести себя в заблуждение их кажущейся простотой и тривиальностью концепции. Как вы увидите позже, ссылки являются чрезвычайно мощным средством, и в некото- рых контекстах позволяют достичь таких результатов, которые без них вообще были бы невозможными.

Что такое ссылка?

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

Объявление и инициализация ссылок

Предположим, вы объявили переменную следующим образом:

После этого вы можете объявить ссылку на эту переменную с помощью такого оператора объявления:

Знак амперсанд, следующий за именем типа long и предшествующий имени пе- ременной rnumber, говорит о том, что это объявление ссылки, а имя переменной, которую она представляет — number — специфицировано как инициализирующее зна- чение, следующее за знаком равенства; таким образом, переменная rnumber имеет тип "ссылка на long". После этого вы можете использовать ссылку вместо имени ис- ходной переменной. Например, оператор:

в качестве эффекта дает увеличение значения переменной number на 10.

Сравните ссылку rnumber с указателем pnumber, объявленным в операторе:

Здесь объявляется указатель pnumber, который инициализируется адресом пере- менной number. Это позволяет увеличивать значение number оператором вроде:

*pnumber +=10; // Инкремент number через указатель

Есть существенная разница между использованием указателя и использованием ссылки. Указатель должен быть разыменован, и адрес, который он содержит, служит для доступа к переменной, участвующей в выражении. В случае ссылки нет необходи- мости в разыменовании. В некотором смысле ссылка подобна указателю, который уже разыменован, хотя его и нельзя заставить ссылаться на другую переменную. Ссылка полностью эквивалентна переменной, на которую она ссылается. Ссылка может пока- заться просто альтернативной нотацией для данной переменной, и здесь она опреде- ленно ведет себя именно таким образом. Однако когда я буду говорить о функциях С++, вы убедитесь, что это не совсем так, и что это средство предлагает некоторые весьма впечатляющие дополнительные возможности.

Программирование на C++/CLI

Динамическое выделение памяти в CLR работает иначе, и CLR поддерживает свою собственную "кучу" памяти, которая полностью независима от кучи родного С++. CLR автоматически очищает память, которая выделена в куче CLR и необходи- мость в которой отпала, поэтому вам не нужно использовать операцию delete в про- граммах, написанных для CLR. CLR может также время от времени упорядочивать память кучи, дабы избежать фрагментации. Таким образом, CLR исключает вероят- ность утечек памяти и ее фрагментации. Управление очисткой кучи, которое пред- усматривает CLR, описывается как сборка мусора (мусор представляет собой отбро- шенные переменные и объекты, а куча, которой управляет CLR, называется кучей, очищаемой сборщиком мусора). Вы используете операцию gcnew вместо new для вы- деления памяти в программе C++/CLI, и префикс дс отражает тот факт, что память выделяется в очищаемой куче, а не в родной куче С++, где за все хозяйство вы отвеча- ете самостоятельно.

Сборщик мусора CLR способен удалять объекты и освобождать память, которую они занимали, когда необходимость в них отпадает. Возникает очевидный вопрос: как может знать сборщик мусора о том, когда объект кучи более не нужен? Ответ до- статочно прост. CLR отслеживает каждую переменную, которая ссылается на каждый объект кучи, и когда не остается переменных, содержащих адрес данного объекта, это значит, что на него невозможно сослаться в программе, а потому он может быть удален.

Поскольку процесс сборки мусора может включать в себя сжатие области памяти кучи для исключения фрагментации неиспользуемых блоков, адрес элемента данных, который вы сохраняете в куче, может измениться. Следовательно, вы не можете при- менять обычные родные указатели С++ с очищаемой кучей, поскольку местоположе- ние указываемых данных изменяется, и такие указатели становятся недействитель- ными. Необходим способ доступа к объектам в куче, который позволяет обновлять адреса, когда сборщик мусора перемещает в ней элементы данных. Эта возможность обеспечивается двумя способами: с помощью отслеживаемых дескрипторов, пред- ставляющих собой некоторые аналоги указателей из родного С++, и посредством от- слеживаемых ссылок — эквивалента родных ссылок С++ в программах CLR.

Отслеживаемые дескрипторы

Отслеживаемые дескрипторы (tracking handle) имеют сходство с родными указа- телями С++, однако есть и существенные отличия. Дескриптор хранит адрес, и адрес, который в нем содержится, автоматически обновляется сборщиком мусора, если объ-

Структурная организация

программ

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

  • Как объявлять и писать собственные функции С++.

  • Как определять и использовать аргументы функций.

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

  • Что означает передача по значению.

  • Как передавать в функции указатели.

  • Как использовать ссылки в качестве аргументов функций, и что означает пере- дача по ссылке.

  • Как модификатор const влияет на аргументы функции.

  • Как возвращать значения из функций.

  • Как использовать рекурсию.

О структурировании программ С++ можно говорить достаточно много, поэтому во избежание несварения желудка, вы не должны пытаться проглотить все сразу. После того, как вы хорошенько разжуете и прочувствуете аромат маленького кусочка, то сможете двинуться дальше, к следующей главе, где получите более подробное пред- ставление об этой теме.