В Турбо Паскале для определения ссылочной переменной нужно описать ее как переменную, имеющую ссылочный тип. В качестве ссылочного можно использовать встроенный тип Pointer или любой другой тип, определенный пользователем следующим образом:
TYPE
ИмяСсылочногоТипа = ^ИмяБазовогоТипа;
где ИмяБазовогоТипа — любой идентификатор типа. В результате
- 195 -
этого определения создаваемые затем ссылочные переменные будут указывать на объекты базового типа, определяя тем самым динамические переменные базового типа. Например:
TYPE { БАЗОВЫЕ ТИПЫ }
DimType = Array [1..10000] of Real; { массив }
RecType = RECORD { запись }
...
END;
ObjType = OBJECT { объект }
...
| END;
{ ССЫЛОЧНЫЕ ТИПЫ }
IntPtr = ^Integer; { ссылка на целое значение }
DimPtr = ^DimType; { ссылка на массив данных }
RecPtr = ^RecType; { ссылка на запись }
ObjPtr = ^ObjТуре; { ссылка на объект }
XXXPtr = Pointer; { ссылка вообще — указатель }
Условимся называть в дальнейшем указателем, а не ссылкой те переменные, которые имеют обобщенный тип Pointer. Этот тип совместим со всеми прочими ссылочными типами.
Все ссылочные переменные имеют одинаковый размер, равный 4 байтам, и содержат адрес начала участка оперативной памяти, в котором размещена динамическая структура данных. Отношение между ссылочной переменной и объектом, на который она указывает, наглядно представлено на рис. 11.1. Здесь J — ссылочная переменная, указывающая на значение целого типа (VAR J : ^Integer). Сравните с простой переменной I типа Integer на том же рисунке.
Рис. 11.1
Чтобы ссылка ни на что не указывала, ей присваивается значение nil, например:
J := nil;
Это предопределенная константа типа Pointer, соответствующая адресу 0000:0000.
- 196 -
11.2. Операция разыменования
Основной операцией при работе со ссылочными переменными является операция разыменования. Суть ее состоит в переходе от ссылочной переменной к значению, на которое она указывает. Эта операция обозначается указанием символа «^» следом за ссылочной переменной. Результатом операции является значение объекта, на который указывала ссылочная переменная, или, что то же самое, динамическая переменная. Так, пусть мы имеем две ссылочные переменные I и J, указывающие на объекты целого типа, значения которых равны 2 (I^) и 4 (J^) соответственно. Для того чтобы скопировать содержимое переменной I^ в переменную J^, необходимо выполнить оператор
J^ := I^;
Следует отметить, что нужно писать именно I^ и J^, поскольку оператор вида
J := I;
приведет к копированию адреса значения, на которое указывает I, в ссылочную переменную J. В этом случае мы получим две ссылки на одно и то же значение. Значение, на которое раньше указывала переменная J, будет потеряно. На рис. 11.2 показан результат выполнения этих двух операторов (а — ситуация до (слева) и после выполнения оператора J^:=I^; б — ситуация до (слева) и после выполнения оператора J:=I). После выполнения оператора J:=I ссылка на значение 4 теряется (рис. 11.2, б, справа), и к нему больше нет доступа.