Храним структуры в динамической памяти

Когда объявляется структура, можно указать ее как динамический тип. Для это­го нужно объявить еще одну переменную и присвоить ей — имяСтруктуры. Чаще всего в качестве нового имени используют то же самое имя, только в начале добав­ляют букву "Р" (это означает Pointer или указатель). Кроме того, объявление это делают прямо перед объявлением структуры:

type

PWindowsSize =  WindowsSize;

WindowsSize = record

Left, Top, Width, Height: Integer;

end;

 

В ЭТОМ примере PWindowsSize— указатель на структуру WindowsSize. Теперь, чтобы разместить нашу структуру не в стеке, а в динамической памяти, мы должны использовать именно

PwindowsSize: var

ws:PWindowsSize;

begin

ws: =New (PWindowsSize) ; / / Выделяем память

ws.Left:=10; // Изменяем одно свойство

Dispose (ws); // Уничтожаем память

end;

 

В этом примере объявлена переменная ws типа PWindowsSize. Это значит, что ws — это всего лишь указатель и в самом начале он нулевой. Теперь надо этому указателю выделить память размером в структуру PWindowsSize. Для этого ей надо присвоить результат работы функции New. Эта функция выделяет динамическую память под указанный в качестве параметра объект и возвращает указатель на эту память. После этого в указателе ws находится выделенная память, подготовленная ДЛЯ использования В качестве структуры PWindowsSize.

Доступ к свойствам остается такой же, поэтому нет смысла задерживаться на этом. Но вот в глаза сразу же бросается вызов функции Dispose. Так как мы выде­лили динамическую память, ее нужно освободить, и для этого служит именно эта функция. Просто передайте ей в качестве параметра указатель, и функция коррект­но обнулит его.

 

Помните, что если вы объявили переменную типа "указатель" на структуру (в нашем примере это pwindowssize), то для такого указателя обязательно нужно сначала выделить память и потом освободить его. Если вы объявляете переменную типа "структура" (в нашем примере это WindowsSize), а не указатель, то такая структура автоматически расположится в стеке и ничего не надо выделять или ос­вобождать.

 

В листинге 10.17 показан пример записи параметров окна в файл, который мы написали в предыдущей главе, но с использованием структуры, расположенной в динамической памяти.

 

procedure TForml.FormClose(Sender: TObject; var Action: TCloseAction);

var

ws:PWindowsSize;

f:TFileStream;

Str:String;

begin

ws: =New (PWindowsSize); // Выделяем память

ws.Left:=Left; // Заполняем левую позицию

ws.Top:=Top; // Заполняем правую позицию

ws.Width:=Width; // Заполняем ширину окна

ws.Height:=Height; // Заполняем высоту окна

f:=TFileStream.Create(1size.dat', fmCreate); // Создаю файл

Size.dat f.Write(wsA, sizeof(wsA)); // Записываю структуру

f.Free; // Закрываю файл

Dispose(ws); // Уничтожаем память end;

 

Обратите внимание, что при записи в файл структуры и определении ее размера мы разыменовываем указатель с помощью записи ws'4. Иначе в файл будет записа­на не структура, а указатель, и при определении размера мы получим размер указа­теля, а не структуры. Это очень важно, потому что вы можете записать в файл недостаточный размер данных или вообще ошибочные данные. Сохранять указа­тель смысла нет, потому что после перезапуска программы этот указатель будет бессмысленным и будет указывать в никуда.

 

Для чтения можно использовать ту же процедуру, что и раньше, без использова­ния указателя. Это связано с тем, что хотя мы и записывали с помощью динамиче­ской структуры, структура данных одна и та же, и в файле будут те же данные, просто записаны они будут по-другому. 

 

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

dle

Помоги проекту! Расскажи друзьям об этом сайте: