Ссылочные типы в ТП

Указатели и динамические переменные


Переменные ссылочного типа (или указатели) описываются в разделе описания переменных, а их тип, указывающий на тип создаваемых в программе, соответствующих динамических объектов определяется либо путем задания типа в описании переменных, либо путем указания имени ранее описанного типа.
Значением указателя является адрес ячейки памяти, начиная с которой будет размещен в памяти соответствующий динамический объект.

Задание ссылочного типа выполняется по схеме:

Type имя ссылочного типа=^ имя типа динамического объекта;

Например: Type mas=array[1..1000] of real;

      Var p,q:^integer; c:^char; a: ^mas;

Эти описания означают, что значениями указателей p и q являются адреса ячеек, где будут размещены динамические переменные целого типа, указатель с – ссылка на динамическую переменную символьного типа, указатель а – ссылка на динамический массив из 1000 вещественных чисел.

Связь указателя с динамическим объектом можно изобразить следующим образом:

Р – имя указателя, звездочкой изображено значение указателя, а стрелка отражает тот факт, что значение указателя является адрес объекта (ссылка на объект), посредством которой объект и доступен в программе

Кроме того, объектом указателя Р является и специальная ссылка nil (ничего), так называемая пустая ссылка, т.е. ссылка, не указывающая ни на какое место в памяти. Результаты выполнения оператора р:=nil можно изобразить следующим образом:

Прежде чем работать с динамическим объектом, необходимо выделить для него место в памяти с помощью процедуры new(p), где р – имя указателя.
Процедура new(p) выполняет две функции:
  1. Резервируется место в памяти для размещения динамического объекта соответствующего типа с именем p^.
  2. Указателю р присваивается адрес создаваемого динамического объекта p^.

Узнать адрес динамической переменной с помощью процедуры writeln(p) нельзя. Динамические объекты размещаются в специальной области памяти, свободной от программ и статических переменных – heap – области.

Пример 1.

var p:^integer; q:integer;
Begin new(p); {порождается динамическая переменная целого типа}
P^:=50; {динамической переменной присвоено значение 50}
Q:=p^+2; p^:=p^ div 3; p^:=q; {допустимые операторы}
P:=q; q:=p+2;p:=p^+3; {недопустимые операторы}
End.

Если в процессе выполнения программы некоторый динамический объект p^, созданный в результате выполнения оператора new(p), становится ненужным, то его можно уничтожить (очистить выделенное ему место в памяти) с помощью стандартной процедуры dispose(p). В результате выполнения этой процедуры значение указателя р становится неопределенным, но не равным nil.

Пример 2.

Program ex2;
Var i:integer; p,q:^integer; {рис.1а}
Begin
New(p); new(q); i:=5; {рис.1б}
P^:=7; q^:=p^-i; i:=i+1; {рис.1в}
P^:=q^+i; q:=p; write(q^); {рис 1г}
End.

Место в памяти, ссылка на которое прежде являлась значением переменной q, теперь стало недоступным: нельзя, например, воспользоваться записанным там значением, нельзя освободить это место с помощью dispose, поскольку на него нет ссылки. Это место в памяти представляет так называемый «мусор». От него следовало бы избавиться с помощью процедуры dispose(q) до изменения значения переменной q. Заменим три последних оператора в программе ех2 на следующую группу операторов: P^:=q^+i; dispose(q);q:=p; write(q^); {рис 2a}

Примечание. Если в ситуации, изображенной на рис.2а, выполнить dispose(p), то место в памяти, ссылка на которое была значением переменных p и q, освободится. После этого не только значение переменной р, но и значение переменной q будет неопределенным.

Стандартные процедуры new и dispose позволяют динамически порождать программные объекты и уничтожать их, что дает возможность использовать память компьютера более эффективно.

Пример 3.

Составить программу, которая в вещественном массиве с 1500 элементами находит элемент, номер которого равен наибольшему значению массива, состоящему из 3000 целых чисел. Алгоритм решения.
  1. организуем динамический массив из целых чисел [1..3000]
  2. найдем в нем наибольший элемент к
  3. освободим память от этого массива и создадим динамический массив действительных чисел
  4. найдем элемент в этом массиве, номер которого равен к.
program ex3;
uses crt;
type ra=array[1..1500]of real;
ia=array[1..3000] of integer;
var k,i:integer;
p:^ra;q:^ia;
Begin
clrscr; randomize; k:=0;
new(q);
for i:=1 to 30 do
begin
q^[i]:=random(15)+6; write(q^[i]:4);
if q^[i]>k then k:=q^[i];
end;
writeln; writeln;
writeln('k= ',k);dispose(q);
new(p);
for i:=1 to 30 do
begin
p^[i]:=random(15)+random; write(p^[i]:5:1);
end;
writeln; writeln;
writeln('iskom element = ', p^[k]:4:1);
readkey;
End.


Назад

Далее