
- •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
192 Глава 4
Если вам нужно применять указатель с многомерными массивами, то нужно ясно представлять, что будет происходить. В качестве иллюстрации можете взять массив, объявленный следующим образом:
Вы можете объявить и присвоить значение указателю pbeans так:
Здесь вы устанавливаете указатель на адрес первого элемента массива, который имеет тип double. Вы также можете установить указатель на адрес первой строки массива с помощью следующего оператора:
Это эквивалентно применению имени одномерного массива, который заменяется его адресом. Мы использовали это в предыдущих дискуссиях; однако поскольку beans — двумерный массив, вы не можете присвоить указателю адрес таким оператором:
Проблема заключается в типе. Тип указателя определен как double*, но массив имеет тип double [3] [4]. Указатель, который может сохранить адрес этого массива, должен быть double* [4]. С++ ассоциирует измерения массива с его типом, и опера- тор, приведенный выше, был бы легальным только в том случае, если бы указатель был объявлен вместе с необходимым измерением. Это делается с применением не- сколько более сложной нотации, чем вы видели до сих пор:
Скобки здесь важны; без них это означало бы объявление массива указателей. С таким объявлением предыдущий оператор корректен, но указатель может использо- ваться только для сохранения адресов массивов с указанным измерением.
Нотация указателей с многомерными массивами
Вы можете использовать нотацию указателей с именами массивов для обращения к их элементам. Обратиться к элементам массива beans, который был объявлен ра- нее, и который имеет три строки по четыре элемента, можно двумя способами.
-
Используя имя массива с двумя значениями индексов.
-
Используя имя массива в нотации указателей. Таким образом, следующие два оператора эквивалентны:
Давайте разберемся, как это работает. В первой строке используется нормальная индексация массива для ссылки на элемент со смещением j в строке i массива.
Вы можете определить значение второй строки, разбирая ее изнутри наружу, beans ссылается на адрес первой строки массива, поэтому beans + i ссылается на строку номер i. Выражение * (beans + i) — это адрес первого элемента строки i, по- этому * (beans + i) + j — адрес элемента в строке i со смещением j. Таким образом, полное выражение ссылается на конкретный элемент массива.
Если вы действительно хотите все запутать (хотя это не рекомендуется), то следу- ющие два оператора, в которых смешивается нотация массивов с нотацией указате- лей, также легально ссылаются на тот же элемент массива:
Существует еще один аспект применения указателей, который на самом деле важ- нее всех остальных: возможность динамического выделения памяти для переменных. Мы рассмотрим это в следующем разделе.
Динамическое выделение памяти
Работа с фиксированным набором переменных в программе может серьезно стес- нять разработчика. Часто в приложениях возникает необходимость в оперативном принятии решений относительно динамического выделения места для размещения переменных различных типов непосредственно во время выполнения — в зависимо- сти от входных данных, полученных программой. Для одного набора данных может быть разумно применять большой массив целых чисел, в то время как другой набор входных данных может потребовать большого массива чисел с плавающей точкой. Понятно, что поскольку динамически распределенные переменные не могут быть определены во время компиляции, они не имеют имен в исходном тексте програм- мы. Когда они создаются, то идентифицируются адресами в памяти, которые сохра- няются в указателях. Благодаря мощности указателей и средствам динамического управления памятью в Visual С++ 2005, написание программ, обладающих такого рода гибкостью, выполняется легко и быстро.
Свободное хранилище, псевдоним "куча"
Во многих случаях, когда выполняется ваша программа, у компьютера есть неис- пользуемая память. Эта неиспользуемая память в С++ называется кучей или, иногда, свободным хранилищем. Вы можете выделить память внутри этого хранилища для новой переменной заданного типа с помощью специальной операции С++, которая возвращает адрес выделенного пространства. Этой операцией является new, и ее до- полняет операция delete, которая освобождает память, ранее выделенную new.
Вы можете выделить память в свободной хранилище для некоторой переменной в одной части программы, а затем освободить выделенное пространство и вернуть его в свободное хранилище после того, как необходимость в этой переменной отпадет. Это позволяет позже в той же программе повторно задействовать эту память для дру- гих динамически распределяемых переменных.
Память из свободного хранилища используется всякий раз, когда возникает по- требность в выделении памяти для элементов, которые могут быть определены лишь во время выполнения. Одним из примеров может служить выделение памяти для строк, вводимых пользователем вашего приложения. Нет способа заранее знать, на- сколько большими должны быть эти строки, поэтому имеет смысл выделять память для них во время выполнения, используя для этого операцию new. Позднее вы озна- комитесь с примером применения свободного хранилища для динамического распре- деления памяти массива, где измерения массива задаются пользователем во время работы программы.
Это может быть очень мощная техника, которая позволяет расходовать память очень эффективно, и во многих случаях разрабатывать программы, способные ре- шать намного более масштабные проблемы, обрабатывая большие объемы данных, чем это возможно без ее применения.