17

私のアプリケーションには、次のレコードがあります。

TTransaction = record
  Alias: string
  Description: string
  Creation: TDateTime
  Count: Integer
end;

そして、私はこの配列でこのレコードを使用しています:

Transactions = array of TTransaction;

実行時に配列をロードしたままにしていますが、特定の時点ですべてのデータをクリアして新しいデータを追加する必要があります。

使用するだけで十分ですか:

SetLength(Transactions, 0); ?

または、何かを確定する必要がありますか?

4

3 に答える 3

17

動的配列に関連付けられているメモリの割り当てを解除するには、次の3つの方法がありますa

SetLength(a, 0);
Finalize(a);
a := nil;

どちらを使用するかはあなた次第です。

ドキュメントには同じことが書かれていますが、ファッションについては少し丸みを帯びています。

動的配列の割り当てを解除するには、配列を参照する変数にnilを割り当てるか、変数をFinalizeに渡します。他に参照がない場合、これらのメソッドのいずれかが配列を破棄します。動的配列は、参照カウントがゼロになると自動的に解放されます。長さ0の動的配列の値はnilです。

これにより、レコードタイプが所有する文字列、動的arryなど、ネストされたマネージタイプを含む、配列に関連付けられたすべてのメモリが解放されます。

将来使用するために配列のサイズを変更する必要があり、新しいデータを使用できるようにする必要がある場合は、を使用してサイズを変更しSetLength、残りの要素を適切に初期化します。

于 2013-02-19T13:27:08.100 に答える
11

配列の長さをゼロに設定すると、配列が破棄されます。これは、「配列をロードしたままにする」という希望に反します。ただし、すべてのレコードとその文字列 (その時点で参照カウントが 1 であるすべての文字列) のメモリが解放されます。

文字列用にメモリを解放したいだけで、割り当てられたレコード メモリを保持する場合 (直後に別のレコード セットを割り当てる予定で、同じメモリを解放して再割り当てする無駄をしたくないため)、その後、文字列メンバーだけをクリアできますが、それを行う単一のライブラリ呼び出しはありません。代わりに、ループを作成し、各レコードのフィールドを自分でクリアする必要があります。

for i := 0 to High(transactions) do begin
  transactions[i].alias := '';
  transactions[i].description := '';
end;

クリアが必要なフィールドがレコード内に多数ある場合TTransactionは、配列の各要素にデフォルト値を割り当てる方が便利な場合があります。関数を使用するか、Delphi の古いバージョンでは、すべてのフィールドがすでにクリアされている をDefault宣言できます。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);
于 2013-02-19T13:23:49.700 に答える
0

SetLength (transactions,0)良い考えではありません。最善の方法は、レコードのすべてのメンバーを再初期化することだと思います。このようにして、変数をロードしたままにします。

SetLength (transactions,0)変数が不要になった場合に使用して、できるだけ少ないメモリを使用することができます。もちろん、プログラムのどこかで再び必要になった場合は、その長さを再調整できます。

クラスではなくレコードであるため、何もファイナライズする必要はありません。クラスのように、レコードにはコンストラクタデストラクタがありません。

于 2013-02-19T13:21:40.357 に答える