Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Электронный конспект лекций (семестр 2).doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
251.39 Кб
Скачать

1.1.9.Массив указателей

Указатели, как и любые другие данные одного и того же типа, могут объединяться в массивы. Массивы указателей можно использовать для работы со всеми типами данных, но целесообразнее применять их для хранения символьных строк.

Объявление

char *ch[10];

означает, что ch – одномерный массив из 10 элементов, являющихся указателями на данные типа char.

Определить и инициализировать массив строк (массив указателей на данные типа char) можно, например, с помощью объявления

char* s[5] = { "one", "two", "three", "four", "five" };

или равнозначного ему

char* s[] = { "one", "two", "three", "four", "five" };

Оба приведенных в примере объявления создают массив указателей s и инициализируют его элементы адресами константных строк. Так как s – массив, указатель s будет содержать адрес начального элемента этого массива, в данном случае – указателя s[0], а каждый из указателей s[0], … , s[4] – адрес начала соответствующей строки. Соответственно, *s, как и s[0], будет означать адрес начала первой по счету строки массива s, а s[0][0], *s[0] (приоритет операции [] выше, чем приоритет операции *) и **s – значение ее начального символа.

1.1.10.Указатели на указатели

Поскольку массив в С++ реализован как указатель на его элементы, то массив указателей неявно определяет новый производный тип данных – указатель на указатель.

Объявление

int **p;

говорит о том, что p – указатель на указатель, то есть содержит адрес другого указателя, а операция *, дважды примененная к указателю p, даст значение типа int. Понятно, что можно определить указатель на указатель на указатель и т.д., то есть переменные с адресами могут образовывать некоторую иерархию (быть многоуровневыми). Например,

int ***v;

определяет указатель на указатель на указатель.

1.1.11.Резервирование и освобождение памяти (операторы new и delete)

Основное назначение указателей состоит в обеспечении возможности работы с динамическими (создаваемыми в процессе выполнения программы) переменными встроенных и производных типов. При такой работе указатели используются как средство хранения адресов резервируемых и освобождаемых участков памяти. Сами же действия, связанные с резервированием и освобождением памяти, осуществляют операторы new и delete.

Оператор new резервирует в области динамической памяти запрошенный участок памяти и возвращает его адрес, а оператор delete освобождает зарезервированный ранее участок памяти. Возможный формат этих операторов:

идентификатор = new тип ;

delete идентификатор ;

Здесь идентификатор – имя указателя, получающего в качестве значения адрес выделенной памяти, достаточной для размещения данных указанного типа. Пример:

int *ip; // указатель на целое значение типа int

...

ip = new int; // резервирование памяти для целого числа

...

delete ip; // освобождение памяти, адресуемой указателем ip

После выполнения последнего оператора примера память, выделенная для переменной типа int и адресуемая указателем ip, становится свободной (недоступной для использования, но доступной для нового резервирования оператором new). Переменная-указатель ip по-прежнему может использоваться в программе, но в текущий момент времени его значение становится неопределенным, указывающим на недоступный участок памяти.

Объявление указателя и резервирование памяти можно объединить:

int *ip = new int; // объявление и инициализация указателя на целое число

Приведенное объявление инициализирует переменную-указатель ip адресом выделенного ей участка памяти для переменной типа int, при этом значение данного участка памяти не определено. Существует возможность применения оператора new с инициализацией выделяемого участка памяти соответствующим значением. Формат оператора new при такой инициализации:

идентификатор = new тип ( значение );

например:

int *ip = new int(10); // выделение участка памяти для целого числа

// и его инициализация значением 10

Последний оператор объявляет переменную-указатель ip, резервирует требуемый участок памяти, присваивает этот адрес объявленной переменной и записывает по данному адресу начальное значение 10.

Для резервирования памяти для одномерного массива следует использовать оператор new формата

идентификатор = new тип [ размер ]

а для его освобождения – оператор delete формата

delete [] идентификатор ;

например:

int *p = new int[5]; // выделение памяти для массива из пяти целых чисел

...

delete []p; // освобождение памяти, зарезервированной для массива p

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

Размер участка памяти, выделяемой для одномерного массива, может задаваться как целочисленным константным выражением, так и выражением, содержащим переменные, например:

int n;

...

cin >> n;

int *p = new int[n]; // выделение памяти для массива из n целых чисел

Инициализация элементов массива, определяемого посредством оператора new, в C++ не предусмотрена.

Не следует забывать о различиях в использовании квадратных и круглых скобок при работе с динамической памятью. Так, оператор:

int *p = new int[n];

осуществляет выделение памяти для массива из n целых чисел, а похожий оператор

int *p = new int(n);

– выделение памяти для одной переменной целого типа с начальным значением n.

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

Для освобождения памяти, динамически (с помощью оператора new) выделенной под двумерный массив a, следует использовать тот же, что и для одномерного массива, оператор

delete []a;

Поскольку при создании динамических массивов всего одна размерность может быть переменной, использование динамических двумерных массивов целесообразно, когда их необходимость заранее неизвестна и зависит от каких-то внешних условий.

Следует подчеркнуть, что динамически (с помощью оператора delete) можно освободить только ту память, которая была динамически (с помощью оператора new) получена.