- •6 Глава 1
- •12 Глава 1
- •14 Глава 1
- •16 Глава 1
- •18 Глава 1
- •20 Глава 1
- •22 Глава 1
- •24 Глава 1
- •26 Глава 1
- •31 Глава 1
- •34 Глава 2
- •36 Глава 2
- •Puc. 2.4. Дополнительные опции консольного приложения Win32
- •38 Глава 2
- •40 Глава 2
- •42 Глава 2
- •44 Глава 2
- •48 Глава 2
- •50 Глава 2
- •52 Глава 2
- •54 Глава 2
- •56 Глава 2
- •58 Глава 2
- •60 Глава 2
- •62 Глава 2
- •64 Глава 2
- •66 Глава 2
- •68 Глава 2
- •70 Глава 2
- •74 Глава 2
- •76 Глава 2
- •79 Глава 2
- •82 Глава 2
- •84 Глава 2
- •86 Глава 2
- •88 Глава 2
- •92 Глава 2
- •94 Глава 2
- •96 Глава 2
- •98 Глава 2
- •103 Глава 2
- •105 Глава 2
- •107 Глава 2
- •110 Глава 2
- •115 Глава 3
- •119 Глава 3
- •121 Глава 3
- •123 Глава 3
- •125 Глава 3
- •129 Глава 3
- •131 Глава 3
- •133 Глава 3
- •139 Глава 3
- •141 Глава 3
- •143 Глава 3
- •145 Глава 3
- •148 Глава 3
- •150 Глава 3
- •155 Глава 3
- •165 Глава 4
- •168 Глава 4
- •170 Глава 4
- •173 Глава 4
- •175 Глава 4
- •178 Глава 4
- •184 Глава 4
- •186 Глава 4
- •188 Глава 4
- •190 Глава 4
- •192 Глава 4
- •194 Глава 4
- •198 Глава 4
- •201 Глава 5
- •203 Глава 5
- •205 Глава 5
- •207 Глава 5
- •213 Глава 5
- •217 Глава 5
- •219 Глава 5
- •221 Глава 5
- •223 Глава 5
- •225 Глава 5
- •227 Глава 5
- •232 Глава 5
- •234 Глава 5
- •236 Глава 5
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 влияет на аргументы функции.
-
Как возвращать значения из функций.
-
Как использовать рекурсию.
О структурировании программ С++ можно говорить достаточно много, поэтому во избежание несварения желудка, вы не должны пытаться проглотить все сразу. После того, как вы хорошенько разжуете и прочувствуете аромат маленького кусочка, то сможете двинуться дальше, к следующей главе, где получите более подробное пред- ставление об этой теме.