Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
На следующем цикле чтения в массив Tek^ будет заноситься очередное текущее слово.
Время выполнения программы, приведенной в данном примере, существенно уменьшается по сравнению с аналогичной программой, использующей только автоматические переменные, за счет отсутствия физической пересылки массивов.
Пояснения к программе, приведенной в данном примере, схематически представляют рисунки 6.6 – 6.9.

Рисунок 6.6 – Результат выполнения
оператора New (Rez)

Рисунок 6.7 – Результат выполнения
оператора Vspom := Rez

Рисунок 6.8 – Результат выполнения
оператора Rez := Tek

Рисунок 6.9 – Результат выполнения
оператора Tek := Vspom
6.2.2. Процедуры Getmem и Freemem
Использование процедур Getmem и Freemem – это второй метод работы с динамическими переменными.
Вызов процедуры Getmem имеет следующий формат:
Getmem (P, Size);
Здесь P - указатель любого типа, Size – выражение типа Word.
Процедура Getmem выделяет из Heap-области (хип-область, область кучи, область динамической памяти) блок памяти заданного размера Size (порождает динамическую переменную размера Size) и адрес этого блока присваивает ссылочной переменной P. Максимальный размер блока – 65521байт (64К байта – $F (смещение)).
Для освобождения блока памяти, занимаемого динамической переменной, используется процедура Freemem:
Freemem (P, Size)
Здесь P – указатель произвольного типа, которому предварительно было присвоено значение процедурой Getmem или оператором присваивания; значение Size должно точно соответствовать размеру переменной, размещенной до этого процедурой Getmem.
Процедура Freemem уничтожает динамическую переменную P^, занимаемая ею память считается свободной, значение P становится неопределенным.
Таким образом, действие процедур Getmem/Freemem аналогично действию процедур New/Dispose – порождается и уничтожается динамическая переменная.
Пример 6.8.
Эквивалентные фрагменты программ, использующие процедуры Getmem/Freemem и New/Dispose.
Type
T = <Тип>;
Var
P: ^T;
…
Begin

В общем случае процедуры Getmem/Freemem дают большую свободу действий по сравнению с процедурами New/Dispose, так как позволяют работать без привязки к конкретному типу переменных.
Пример 6.9.
Использование процедур Getmem/Freemem. Различная интерпретация выделенной области памяти.
Type
Zap = Record
X, Y: Integer;
End;
St = String [20];
Var
P: Pointer;
Begin
Getmem (P, 100); {Выделение блока памяти размером 100 байт, адрес этого блока присвоен ссылочной переменной Р}
Zap(P^).X := 124; {Интерпретация выделенной области как записи – блоку памяти, связанному с указателем Р, присваивается тип Zap}
Zap(P^).Y := 47; {Интерпретация выделенной области как записи}
…
Real(P^) := 0.213; {Интерпретация выделенной области как Real}
…
St(P^) := ’ПРОГРАММИРОВАНИЕ’; {Интерпретация выделенной области как строки}
…
Freemem (P, 100); {Освобождение блока памяти размером 100 байт}
…
6.2.3. Процедуры Mark и Release
Процедуры Mark (пометить) и Release (освободить) позволяют повысить эффективность работы с динамической памятью.
Обращение к процедуре Mark имеет следующий вид:
Mark (P1);
Здесь P1 – переменная типа указатель, ссылающаяся на переменную какого угодно типа.
Процедура Mark присваивает своему параметру P1 адрес начала свободной области динамической памяти.
Помеченная область с помощью процедур New или Getmem используется для размещения отдельных динамических переменных.
Когда данные динамические переменные окажутся ненужными, занимаемую ими память можно освободить. Для этого используется процедура Release с тем же параметром, что и в предыдущем обращении к процедуре Mark:
Release (P1);
Процедура Release освобождает память, начиная с адреса, полученного в результате выполнения последней процедуры Mark. Значение указателя P1 после выполнения процедуры Release равно Nil.
Схематически представление работы с динамической памятью без и с использованием процедур Mark/Release иллюстрирует рисунок 6.10.

Рисунок 6.10 – Схематическое представление
работы с динамической памятью
без и с использованием процедур Mark/Release
Параметр процедуры Mark нельзя использовать в качестве параметра процедур New, Getmem и его нельзя изменять (по крайней мере до его использования в соответствующей процедуре Release).
Возможна вложенность процедур Mark. Тогда каждой процедуре Mark соответствует своя процедура Release.
Пример 6.10.
Использование вложенных процедур Mark/Release.

В одной и той же программе не рекомендуется использовать одновременно процедуры Dispose или Freemem и Mark/Release, так как это может привести к непредсказуемым результатам (механизмы управления свободной памятью для процедур Dispose, Freemem и Mark/Release существенно различаются).
В общем случае вместо любой автоматической переменной в программе можно использовать динамическую переменную.
Основное достоинство использования динамических переменных – экономия памяти компьютера.
Недостатки использования динамических переменных по сравнению с автоматическими:
- удлиняется текст программы за счет использования процедур New/Dispose, Mark/Release, Getmem/Freemem; снижается наглядность программы за счет использования переменной с указателем (динамической переменной); снижается быстродействие программы за счет необходимости во время ее выполнения размещать порожденную динамическую переменную в памяти машины, за счет формирования значения соответствующего указателя и за счет усложнения доступа к значению динамической переменной.
Раздел 7. Динамические структуры данных
7.1. Динамические цепочки
7.1.1. Структура динамической цепочки
Динамические цепочки являются аналогами строк текущей длины.
В строке каждый следующий элемент занимает ячейку памяти со следующим по порядку адресом.
Элементы строки можно размещать в памяти произвольно, если каждый элемент снабдить явным указанием места, где находится следующий за ним элемент. В этом случае каждый элемент строки должен состоять из двух полей: в одном поле (Element) – символ сроки, в другом (Adrcled) – ссылка на следующий элемент строки (адрес следующего элемента).
Каждая такая пара называется звеном. Ссылки сцепляют звенья в одну цепочку.
Такой способ представления упорядоченной последовательности элементов называется сцеплением. Сцепление применяется для представления любых сложных динамических структур данных – строк, списков, деревьев и так далее. В этом случае звено всегда состоит из двух частей – тела звена (элемента последовательности) и справочной части (ссылки на другие элементы структуры).
Таким образом, для представления звена необходимо использовать запись, состоящую из двух полей.
Пример 7.1.
Объявление звена цепочки.
Type
Adr = ^Zveno;
Zveno = Record
Element: Char;
Adrcled: Adr
End;
В примере 7.1 тип Adr представляет собой ссылки на программные элементы типа Zveno.
В данном примере имя типа Zveno используется до его описания при описании типа Adr (ссылочного типа). Ссылочный тип – единственный тип, где можно использовать имя до его описания. Обратную последовательность объявлений (вначале описать тип Zveno, а потом – тип Adr) в примере 7.1 использовать было бы нельзя (так как в типе Zveno используется неописанный тип Adr, а Zveno не является ссылочным типом).
Последнее звено цепочки должно быть снабжено ссылкой Nil (это признак конца цепочки).
Для работы с цепочкой необходимо использовать два указателя: ссылку на ее первое звено (Adr1) и ссылку на текущее звено (Adrzv). Ссылки должны иметь тип Adr. Например,
Var Adr1, Adrzv: Adr;
Схематично цепочка может быть представлена так, как изображает рисунок 7.1.

Рисунок 7.1 – Схематическое представление цепочки
Для удобства работы с цепочкой в нее обычно включается заглавное «нулевое» звено (хотя это и не обязательно). В поле Adrcled данного звена содержится ссылка на первое звено цепочки (его адрес). Поле Element может быть использовано для хранения какой-либо информации о строке.
7.1.2. Формирование цепочки
Пусть имеется объявление звена цепочки, соответствующее примеру 7.1.
Алгоритм формирования цепочки:
Отвести область памяти для очередного звена. Его адрес занести в поле Adrcled текущего звена. Новое звено сделать текущим (занести его адрес в указатель текущего звена Adrzv). В поле Element текущего звена занести очередной символ. В поле Adrcled текущего звена занести Nil. Прочитать следующий символ исходного текста. Повторить этапы алгоритма, начиная с первого этапа.Предварительно перед выполнением этапов 1 – 6 алгоритма необходимо сформировать заглавное звено.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |


