私は常にメモリ使用量を念頭に置いてアプリケーションを作成しようとしています。必要がない場合は作成しないでください。これが私の見方です。
とにかく、例として以下を取り上げます。
Form2:= TForm2.Create(nil);
try
Form2.ShowModal;
finally
Form2.FreeOnRelease;
end;
私は実際にForm2.Destroyがおそらくより良いオプションだと思います。それは私の質問に私をもたらします。
呼び出しの違いは何ですか:
Form2.Destroy;
Form2.Free;
Form2.FreeOnRelease;
私が何かを逃していない限り、それらはすべて同じまたは同様の仕事をします。
また、上記のいずれかをいつ使用する必要がありますか?オブジェクトを解放するときは明らかにそれを理解していますが、状況によっては、たとえばDestroy
よりもFree
の方が適していますか?
Form2:= TForm2.Create(nil);
Form2
はおそらく、IDEで作成されたTForm2
を通常保持する、IDEで生成されたグローバル変数であるため、これはコードの臭いです。ほとんどの場合、ローカル変数と、より適切な名前の変数を使用することをお勧めします。これは必ずしもエラーではなく、コードの臭いです。
Form2.DestroyとForm2.Free
とにかくDestroy
を呼び出すので、Form2.Free
を使用します。あなたはできる CTRL+Click 名前(Free
)で、その実装を確認します。基本的に、Free
がnilでない場合、Destroy
はSelf
を呼び出します。
Form2.FreeOnRelease
ドキュメント が言うように、"It should not be necessary to call FreeOnRelease directly."
FreeOnRelease
についてはこれまで聞いたことがありません。グーグルですばやく検索すると、その理由がわかりました。 公式ドキュメントから:
FreeOnReleaseは、コンポーネントによって実装されたインターフェースが解放されたときに呼び出されます。 FreeOnReleaseは内部で使用され、対応するインターフェイスメソッドを呼び出します。 FreeOnReleaseを直接呼び出す必要はありません。
Free
とDestroy
については、Free
が安全機能です。基本的にはif self <> nil then self.Destroy;
として実装され、コンストラクタとデストラクタを安全に使用できるようにするために作成されました。基本的な考え方は次のとおりです。
オブジェクトを作成していて、未処理の例外が発生した場合、デストラクタが呼び出されます。オブジェクトに他のオブジェクトが含まれている場合、エラーが発生するまでにオブジェクトがまだ作成されている場合とされていない場合があるため、すべてのオブジェクトでDestroy
を呼び出そうとすることはできません。ただし、作成されたものが確実に破棄されるようにする方法が必要です。
Delphiはコンストラクタを呼び出す前にオブジェクトのアドレス空間をゼロにするため、まだ作成されていないものはすべて、この時点でnilであることが保証されます。したがって、すべてのサブオブジェクトに対して何度もif FSubObject <> nil then FSubObject.Destroy
と言うことができます(アクセス違反が発生することを忘れた場合)。または、Free
メソッドを使用できます。あなたのためにそれ。 (これは、コンストラクターが呼び出される前にメモリスペースが not ゼロになるC++に比べて大幅に改善されています。これには、すべてのサブオブジェクトをスマートポインターでラップし、RAIIを使用して例外安全性を維持してください!)
他の場所でも便利で、使わない理由はありません。 Free
が測定可能なパフォーマンスの低下をもたらし、コードの安全性が向上することに気づいたことはありません。したがって、すべての場合に使用することをお勧めします。
そうは言っても、フォームを具体的に扱う場合、方程式に組み込む追加の変数があります。それはWindowsメッセージキューです。解放しようとしているフォームの保留中のメッセージがまだあるかどうかわからないため、フォームでFree
を呼び出すことが常に安全であるとは限りません。そのために、Release
メソッドがあります。キューにメッセージを投稿して、処理するメッセージがなくなるとフォームが自動的に解放されるようにするため、通常は、不要になったフォームを解放するための最良の方法です。
正規の形式は次のとおりです。
Form := TMyForm.Create(nil);
try
Form.ShowModal;
finally
Form.Free;
end;
Destroy
を呼び出さないでください。代わりに、常にFree
を呼び出してください。
FreeOnRelease
は完全に赤いニシンです。フォームまたはその子宛てのキューに入れられたメッセージがある場合は、Release
を呼び出すことを選択する場合がありますが、多くの場合、これは設計上の問題を示しています。
慣用的な用法は
_procedure SomeProc;
var
frm: TForm2;
begin
frm := TForm2.Create(nil);
try
frm.ShowModal;
finally
frm.Free;
end;
end;
_
または、with
構文が嫌いでない限り、
_with TForm2.Create(nil) do
try
ShowModal;
finally
Free;
end;
_
ドキュメント によると、決してDestroy
を呼び出さないでください。実際、Free
は_if Self <> nil then Destroy;
_とまったく同じです。つまり、これはDestroy
の「安全な」バージョンです。ポインタがたまたまnil
の場合、完全にクラッシュすることはありません。 [これをテストするには、フォームクラスにプライベートフィールド_FBitmap: TBitmap
_を追加してから、(たとえば)OnCreateで_FBitmap.Free
_と_FBitmap.Destroy
_を試してください。]
上記のアプローチを使用してフォームを作成する場合、フォームクラスで奇妙なことをしない限り、Free
は完全に安全です。
ただし、CreateForm(TForm2, Form2)
を使用してフォームを作成し、フォームオブジェクトをグローバルインスタンス変数_Form2
_に格納し、すぐに解放しない場合[たとえば、ウィンドウを固定したい場合メインフォームの横で非モーダルな方法で数分間]、おそらくRelease
の代わりにFree
を使用する必要があります。から ドキュメント 、
リリースは、フォームのすべてのイベントハンドラーとフォーム上のコンポーネントのイベントハンドラーの実行が終了するまでフォームを破棄しません。リリースは、フォームがリリースされる前に、フォームのイベントキュー内のすべてのメッセージが処理されることも保証します。フォームまたはその子のイベントハンドラーは、Free(Delphi)またはdelete(C++)の代わりにReleaseを使用する必要があります。そうしないと、メモリアクセスエラーが発生する可能性があります。
FreeOnRelease
フォームとは特に関係ありません。ドキュメントから:
FreeOnReleaseを直接呼び出す必要はありません。
もう1つの方法は、caFreeをformoncloseのアクションに渡すことです。
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end