Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
###Cpp_лкц1_1.09_11_#дляБАК#29_01_12.doc
Скачиваний:
39
Добавлен:
29.04.2019
Размер:
6.42 Mб
Скачать

Int* p (&а); // то же самое другим способом

■ с помощью значения другого инициализированного указателя:

int* г = р;

■ с помощью имени массива или функции, которые трактуются как адрес (см. «Массивы», с. 58, и «Передача имен функций в качестве параметров», с. 80):

int b[10]; // массив

int* t = b; // присваивание адреса начала массива

void f(int a ){ /* ... */ } // определение функции

void (*pf)(int): // указатель на функцию

pf = f; // присваивание адреса функции

2. Присваивание указателю адреса области памяти в явном виде:

char* vp = (char *)0xB8000000;

Здесь 0хВ8000000 — шестнадцатеричная константа, (char *) — операция приведения типа: константа преобразуется к типу «указатель на char».

54

Часть I. Структурное программирование

3. Присваивание пустого значения:

int* suxx = NULL; int* rulez = 0;

В первой строке используется константа NULL, определенная в некоторых заголовочных файлах С как указатель, равный нулю. Рекомендуется использовать просто 0, так как это значение типа i nt будет правильно преобразовано стандартными способами в соответствии с контекстом. Поскольку гарантируется, что объектов с нулевым адресом нет, пустой указатель можно использовать для проверки, ссылается указатель на конкретный объект или нет.

4. Выделение участка динамической памяти и присваивание ее адреса указателю:

■ с помощью операции new:

int* n = new int; // 1

int* m = new int (10); // 2

int* q = new int [10]; // 3

■ с помощью функции mall ос1:

int* u = (int *)malloc(sizeof(int)); // 4

В операторе 1 операция new выполняет выделение достаточного для размещения величины типа i nt участка динамической памяти и записывает адрес начала этого участка в переменную п. Память под саму переменную п (размера, достаточного для размещения указателя) выделяется на этапе компиляции.

В операторе 2, кроме описанных выше действий, производится инициализация выделенной динамической памяти значением 10.

В операторе 3 операция new выполняет выделение памяти под 10 величин типа int (массива из 10 элементов) и записывает адрес начала этого участка в переменную q, которая может трактоваться как имя массива. Через имя можно обращаться к любому элементу массива. О массивах рассказывается на с. 58.

Если память выделить не удалось, по стандарту должно порождаться исключение bad_alloc (об исключениях рассказывается в разделе «Обработка исключительных ситуаций», с. 222, а об обработке ошибок выделения памяти — на с. 378). Старые версии компиляторов могут возвращать 0.

В операторе 4 делается то же самое, что и в операторе 1, но с помощью функции выделения памяти та 11 ос, унаследованной из библиотеки С. В функцию передается один параметр — количество выделяемой памяти в байтах. Конструкция (int*) используется для приведения типа указателя, возвращаемого функцией, к требуемому типу (о явном преобразовании типов см. с. 231). Если память выделить не удалось, функция возвращает 0.

Операцию new использовать предпочтительнее, чем функцию mall ос, особенно при работе с объектами.

Освобождение памяти, выделенной с помощью операции new, должно выполняться с помощью delete, а памяти, выделенной функцией та 11 ос — посредством

Для того чтобы использовать malloc, требуется подключить к программе заголовочный файл <malloc.h>.

Глава 1. Базовые средства языка C++

55

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

delete n; delete m; delete [] q; free (u);

Если память выделялась с помощью new[], для освобождения памяти необходимо применять delete[]. Размерность массива при этом не указывается. Если квадратных скобок нет, то никакого сообщения об ошибке не выдается, но помечен как свободный будет только первый элемент массива, а остальные окажутся недоступны для дальнейших операций. Такие ячейки памяти называются мусором.

ВНИМАНИЕ

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

С помощью комбинаций звездочек, круглых и квадратных скобок можно описывать составные типы и указатели на составные типы, например, в операторе

int *(*р[Ю])(): объявляется массив из 10 указателей на функции без параметров, возвращающих указатели на i nt.

По умолчанию квадратные и круглые скобки имеют одинаковый приоритет, больший, чем звездочка, и рассматриваются слева направо. Для изменения порядка рассмотрения используются круглые скобки.

При интерпретации сложных описаний необходимо придерживаться правила «изнутри наружу»:

  1. если справа от имени имеются квадратные скобки, это массив, если скобки круглые — это функция;

  2. если слева есть звездочка, это указатель на проинтерпретированную ранее конструкцию;

  3. если справа встречается закрывающая круглая скобка, необходимо применить приведенные выше правила внутри скобок, а затем переходить наружу;

  4. в последнюю очередь интерпретируется спецификатор типа.

Для приведенного выше описания порядок интерпретации указан цифрами:

int *(*р[10])():