Когда объявляется структура, можно указать ее как динамический тип. Для этого нужно объявить еще одну переменную и присвоить ей — имяСтруктуры. Чаще всего в качестве нового имени используют то же самое имя, только в начале добавляют букву "Р" (это означает 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. Иначе в файл будет записана не структура, а указатель, и при определении размера мы получим размер указателя, а не структуры. Это очень важно, потому что вы можете записать в файл недостаточный размер данных или вообще ошибочные данные. Сохранять указатель смысла нет, потому что после перезапуска программы этот указатель будет бессмысленным и будет указывать в никуда.
Для чтения можно использовать ту же процедуру, что и раньше, без использования указателя. Это связано с тем, что хотя мы и записывали с помощью динамической структуры, структура данных одна и та же, и в файле будут те же данные, просто записаны они будут по-другому.
Если вы решите при загрузке использовать структуру в динамической памяти, то перед чтением не забудьте выделить память.