Нужно ли мне дорабатывать массив записей в Delphi?
В моем приложении у меня есть следующая запись:
TTransaction = record
Alias: string
Description: string
Creation: TDateTime
Count: Integer
end;
и я использую эту запись в этом массиве:
Transactions = array of TTransaction;
Я сохраняю массив загруженным во время выполнения, но в данный момент мне нужно очистить все данные и добавить некоторые новые.
Достаточно ли просто использовать:
SetLength(Transactions, 0); ?
Или мне нужно что-то финализировать?
Ответы
Ответ 1
Существует три способа освобождения памяти от связей с динамическим массивом, a
:
SetLength(a, 0);
Finalize(a);
a := nil;
Это зависит от того, какой из них использовать.
Документация говорит то же самое, хотя и слегка круглая:
Чтобы освободить динамический массив, назначьте nil переменной, которая ссылается на массив или передает переменную в Finalize; любой из этих методов предоставляет массив, если нет других ссылок на него. Динамические массивы автоматически освобождаются, когда их счетчик ссылок падает до нуля. Динамические массивы длины 0 имеют значение nil.
Это освободит всю память, связанную с массивом, включая любые вложенные управляемые типы, такие как строки, динамические arrys и т.д., которые принадлежат типу вашей записи.
Если вам нужно изменить размер массива для будущего использования и получить новые данные, просто измените размер с помощью SetLength
и соответствующим образом инициализируйте остальные элементы.
Ответ 2
Установка длины массива в ноль приведет к уничтожению массива, что противоречит вашему желанию "сохранить массив загруженным". Тем не менее, он освободит память для всех записей и их строк (для любых строк, счетчик ссылок которых равен 1 в то время).
Если вы просто хотите освободить память для строк, но сохраните выделенную память записи (потому что вы планируете сразу же назначить другой набор записей, и вы не хотите тратить время на освобождение и перераспределение того же память), тогда вы можете очистить только члены строки, но нет единого вызова библиотеки, чтобы сделать это для вас. Вместо этого вам нужно написать цикл и очистить все поля записи самостоятельно.
for i := 0 to High(transactions) do begin
transactions[i].alias := '';
transactions[i].description := '';
end;
Если в записи есть много полей, требующих очистки, тогда было бы удобнее назначить значение по умолчанию TTransaction
для каждого элемента массива. Вы можете использовать функцию Default
, или в более старых версиях Delphi вы можете объявить TTransaction
, у которого все поля уже очищены:
const
ClearTransaction: TTransaction = (alias: ''; description: ''; creation: 0; count: 0);
for i := 0 to High(transactions) do
transactions[i] := ClearTransaction;
// or
transactions[i] := Default(TTransaction);
Ответ 3
SetLength (transactions,0)
- не очень хорошая идея. Я думаю, что лучший способ - повторить инициализацию всех участников записи. Таким образом, вы сохраняете переменную.
Вы можете использовать SetLength (transactions,0)
, если вам больше не нужна переменная, чтобы использовать как можно меньше памяти. Конечно, если вам это нужно снова где-то в программе, вы можете изменить его длину, предположите, что знаете это.
Вам не нужно ничего финализировать, потому что это запись, а не класс. В записях нет конструкторов или деструкторов, например классов.