2013-02-19 5 views
14

私は、次のレコードを持っている:Delphiでレコードの配列を完成させる必要がありますか?私のアプリケーションで

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

と、私はこの配列内でこのレコードを使用しています:私は実行時にロードされた配列を維持しています

Transactions = array of TTransaction; 

が、で与えられたが私はすべてのデータをクリアし、新しいものを追加する必要があります。

は、それは十分だけ使用することです:

SetLength(Transactions, 0); ? 

それとも私が何かを確定する必要がありますか?

答えて

15

動的配列、aでメモリ仲間の割り当てを解除するには、3つの方法があります。

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

使用するのはあなた次第です。

documentationファッション約ややラウンドではあるが、同じことを言う:

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

これは、レコードタイプが所有する文字列、動的アライなどのネストされた管理対象タイプを含め、配列に関連付けられたすべてのメモリを解放します。

今後の使用のために配列のサイズを変更し、新しいデータを使用可能にする必要がある場合は、SetLengthを使用してサイズを変更し、残りの要素を適切に初期化してください。

+1

'Finalize'は実際に' a'の値を変更しますか?私は常に 'Free'または' Initialize'の呼び出しを予期して、 'a'に格納された動的配列の元のアドレスを残しながらメモリを解放するという印象の下にいました。 –

+1

@Robダイナミックアレイの場合、これらの3つのオプションはすべて同等です。管理型の場合、Finalizeは参照をnilに設定する必要があります。それは選択肢がありません。動的配列型のローカル変数を考えてみましょう。 –

+0

@DavidHeffernan配列の最高の境界が10の場合は、以下を使用する方が良いでしょう:1- Nilに設定し、すべてを再作成します。 2 - 使用されたインデックスを次の値に関連付けますか? – EProgrammerNotFound

0

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

可能な限り小さなメモリを使用するために、変数が不要な場合はSetLength (transactions,0)を使用できます。もちろん、プログラムのどこかでもう一度それが必要な場合は、あなたがそれを知っていると仮定して、その長さを再調整することができます。

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

+0

* "あなたは長さを調整することができます" * - しかし、おそらくすべての古いアイテムをすべての静的コンテンツでコピーし、動的コンテンツ(文字列、dyn配列)増減する。そのため、場合によっては長さを変更する前に完全配列の割り振り解除を使用しています。 *すべてのレコードフィールドが単純な型(文字列/ dyn配列/インターフェースではない)である場合にのみtrueです。* "あなたは何かを完成させる必要はありません。 – Fr0sT

10

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

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

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

クリアする必要があるレコードのフィールドがたくさんある場合、配列の各要素にデフォルトTTransaction値を代入する方が便利かもしれません。あなたは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); 
+0

私はこれが最善の策だと思っています。なぜなら、いつすべてのデータを再ロードしたいのかを決めるユーザーは、レコード型が構造体であり、私の場合はプリミティブ型であると分かりました。お返事ありがとうございます – EProgrammerNotFound

+0

ここの答えの2番目の部分に記載されているトピックに触れる既存の質問は:http://stackoverflow.com/questions/11065821/how-to-properly-free-records-that-c​​ontain-いろいろなタイプのデルファイアットワンス –

+0

@DavidHeffernan私はその話題を読んだので、私はファイナライズについて質問しました。私は非常に多くの答えと混乱し、その人はファイナライズ+ fillcharについて話しています... – EProgrammerNotFound