- •4.9.1. Изменяемость
- •4.9.2. Классы операций
- •98 Глава 4
- •4.9.3. Полнота
- •100 Глава 4
- •4.9.5. Операции egual, similar и copy
- •102 Глава 4
- •104 Глава 4
- •5. Исключительные ситуации
- •108 Глава 5
- •110 Глава 5
- •6.2.1. Сигнализация об исключительных ситуациях
- •5.2.2. Обработка исключительных ситуаций
- •112 Глава 5
- •5.2.3. Предложение resignal
- •6.2.4. Необрабатываемые исключительные ситуации
- •114 Глава 5
- •6.2.3. Предложение resignal
- •5.2.4. Необрабатываемые исключительные ситуации
- •116 Глава 5
- •118 Глава 5
- •118 Глава 5
- •120 Глава 5
- •122 Глава 5
- •124 Глава 5
- •128 Глава 6
- •130 Глава 6
- •6.2.1. Реализация итераторов
- •6.2.2. Использование итераторов
- •132 Глава 6
- •134 Глава 6
- •136 Глава 6
- •138 Глава 6
- •140 Глава 7
- •142 Глава 7
- •7.2. Абстракция данных
- •144 Глава 7
- •146 Глава 7
- •148 Глава 7
- •150 Глава 7
- •7.4. Генераторы
- •162 Глава 7
- •154 Глава 7
- •156 Глава 7
- •162 Глава 8
- •164 Глава 8
- •166 Глава 8
- •168 Глава 8
- •170 Глава 9
- •172 Глава 9
- •174 Глава 9
- •176 Глава 9
- •9.1.3. Пример
- •178 Глава 9
- •180 Глава 9
- •182 Глава 9
- •184 Глава 9
- •186 Глава 9
- •188 Глава 9
- •190 Глава 9
- •192 Глава. 9
- •194 Глава 9
144 Глава 7
intqueue = data type is q_new, q.isempty, q_append,
q-remfirst
Описание
Типы данных intqueue используются для хранения значений типа целого числа. Элементы могут извлекаться из очереди или удаляться из нее только методом обратного магазинного типа («первым пришел — первым обслужен») Операции function q_new: intqueue
effects Возвращает новую очередь без элементов в ней. function qJsempty (q: intqueue): boolean
effects Возвращает значение true, если в очереди q нет элементов, в противном случае возвращает значение false. procedure q .append (q; intqueue; e: integer) modifies q
effects Добавляет элемент e в конец очереди q. function q_rernfirst (q: intqueue): integer requires чтобы очередь q была не пустой, modifies q effects Возвращает элемент из начала очереди q и удаляет этот элемент из
очереди q. end intqueue
Рис. 7.1. Спецификация очереди целых чисел.
кой, чтобы гарантировать то, что абстрактные объекты могут быть возвращены при помощи функций. Если бы, например, представление было некоторой записью, содержащей в качестве своей компоненты некоторый указатель, то его нельзя было бы вернуть при помощи функции. И наконец, использование указателя га-раш нрует эффективность при передаче абстрактных объектов по значению.
По соглашению объявление типа представления всегда будет в такой форме:
type type: iai-ne == ^typename.rep;
где typename.rep является некоторым типом, который описывает «реальное» представление. Например, для типа intqueue мы используем такой тип представления:
type
intqueue = ^intqueue.rep; intqueue. rep = '[•intqLleue.elem; intqueue_elem == record val: integer; next: intqueue. rep; end;
Следуя нашим соглашениям, просто объявить переменные некоторого абстрактного типа, например,
var q: intqueue;
Смысл этого объявления состоит в том, что в стеке отводится пространство для некоторой неинициализированной переменной q.
Использование языка Паскаль
Размер этого пространства такой, чтобы поместился некоторый указатель, как в языке CLLJ.
Когда очередь q объявлена, выделяется только указатель, и, следовательно, когда организуется выход из процедуры, в которой объявлена очередь q, освобождается только этот указатель. Место для элементов очереди q выделяется в операциях типа intqueue при помощи явных обращений к примитиву new языка Паскаль. Поскольку в языке Паскаль сборка мусора автоматически не осуществляется, пространство, занятое этими элементами, должно быть явно освобождено той программой, в которой используется данная очередь. Для этой цели в языке Паскаль имеется примитив dispose. Указатель задается как аргумент для этого примитива, он следует этому указателю и освобождает то пространство, на которое указывает данный указатель. Размер освобождаемого пространства зависит от типа указателя. Примитив dispose (q) будет освобождать пространство, занятое одним указателем типа intqueue.rep. Это означает, что вся память, занимаемая элементами, будет оставаться занятой, и это может привести к особенно неприятной ошибке в программе, называемой «утечкой памяти». Утечка памяти происходит тогда, когда не была освобождена память, которая должна быть освобождена. Единственным симптомом этой ошибки является то, что через некоторое время неупорядоченный массив постепенно исчерпывается. К тому времени, когда в программе кончится такое пространство, может выполниться очень много команд от того места, где произошла сама утечка.
Чтобы гарантировать правильное освобождение пространсчЕа, для каждого типа дожна существовать некоторая дополнительная операция, которая называется destroy. Операция destroy использует один аргумент — некоторый объект данного типа, и она освобождает все пространство в неупорядоченном массиве, связанное с этим объектом. Значение данного объекта при возврате из операции destroy не определено. Приведем спецификацию процедуры q.destroy.
procedure q. destroy (q: intqueue) modilSes q
efiects В неупорядоченном массиве освобождается вся память, занимаемая очередью q.
По соглашению пользователи никогда не освобождают абстрактные объекты непосредственно. Вмесго этого они обращаются к операции destroy для типа данного объекта. При этом соглашении размер освобождаемого пространства находится под контролем. При этом, однако, не гарантируется, что к освобожденному объекту не будет больше ссылок. Если такая ссылка существует, то после освобождения данного объекта она становится «повисающей ссылкой». Если делается попытка получить доступ
