18

私は常にメモリ使用量を念頭に置いてアプリケーションを作成しようとしていますが、必要ない場合は作成しないでください。

とにかく、例として次のことを考えてみましょう。

Form2:= TForm2.Create(nil);
try
  Form2.ShowModal;
finally
  Form2.FreeOnRelease;
end;

私は実際に Form2.Destroy がおそらくより良いオプションだと思います。それが私の質問につながります..

呼び出しの違いは何ですか:

Form2.Destroy;
Form2.Free;
Form2.FreeOnRelease;

私が何かを見逃していない限り、それらはすべて同じまたは同様の仕事をします。

また、上記のいずれかをいつ使用する必要がありますか? 明らかに、オブジェクトを解放するときはそれを理解していますが、状況によっては、たとえばDestroyよりも適していますか?Free

4

5 に答える 5

16

Form2:= TForm2.Create(nil);

これはコードの臭いです。これForm2はおそらく、通常はIDEで作成されたを保持するグローバルなIDEで生成された変数であるためですTForm2。ほとんどの場合、ローカル変数と、より適切な名前の変数を使用することをお勧めします。これはエラーである必要はなく、コードの臭いだけです。

Form2.DestroyとForm2.Free

とにかくForm2.Free呼び出すので、を使用します。+名前()に+を付けて、その実装を確認Destroyできます。基本的に、がnilでない場合は呼び出します。CTRLClickFreeFreeDestroySelf

Form2.FreeOnRelease

ドキュメントにあるように、"It should not be necessary to call FreeOnRelease directly."

于 2011-06-10T18:55:21.843 に答える
10

私は実際にこれまで聞いたことがありませんFreeOnRelease。グーグルですばやく検索すると、その理由がわかりました。 公式ドキュメントから:

FreeOnReleaseは、コンポーネントによって実装されたインターフェースが解放されたときに呼び出されます。FreeOnReleaseは内部で使用され、対応するインターフェイスメソッドを呼び出します。FreeOnReleaseを直接呼び出す必要はありません。

Free対に関してはDestroyFreeは安全機能です。基本的にはとして実装されif self <> nil then self.Destroy;、コンストラクタとデストラクタを安全に使用できるようにするために作成されました。基本的な考え方は次のとおりです。

オブジェクトを作成しているときに未処理の例外が発生した場合、デストラクタが呼び出されます。オブジェクトに他のオブジェクトが含まれている場合、エラーが発生するまでにオブジェクトがまだ作成されている場合とされていない場合があるためDestroy、すべてのオブジェクトを呼び出すことはできません。ただし、作成されたものが確実に破棄されるようにする方法が必要です。

Delphiはコンストラクターを呼び出す前にオブジェクトのアドレス空間をゼロにするため、まだ作成されていないものはすべて、この時点でゼロであることが保証されます。したがって、すべてのサブオブジェクトについて何度も何度も言うことができますif FSubObject <> nil then FSubObject.Destroy(そして、アクセス違反が発生することを忘れた場合)、またはFreeメソッドを使用することができます。(これは、コンストラクターが呼び出される前にメモリスペースがゼロにされないC ++に比べて大幅に改善されています。これには、すべてのサブオブジェクトをスマートポインターでラップし、RAIIを使用して例外安全性を維持する必要があります!)

他の場所でも便利で、使わない理由はありません。これが測定可能なパフォーマンスの低下をもたらすことに気づいたことはなくFree、コードの安全性が向上するため、すべての場合に使用することをお勧めします。

そうは言っても、フォームを具体的に扱う場合、方程式に組み込む追加の変数があります。それはWindowsメッセージキューです。解放しようとしているフォームの保留中のメッセージがまだあるかどうかわからないため、フォームを呼び出すことが常に安全であるとは限りませんFree。そのためのRelease方法があります。キューにメッセージを投稿し、処理するメッセージがなくなるとフォームが自動的に解放されるため、通常は、不要になったフォームを解放するための最良の方法です。

于 2011-06-10T18:51:52.583 に答える
6

標準形式は次のとおりです。

Form := TMyForm.Create(nil);
try
  Form.ShowModal;
finally
  Form.Free;
end;

を呼び出さないで、代わりDestroyに常に呼び出しFreeます。

FreeOnRelease完全な赤いニシンです。フォームまたはその子に宛てられたメッセージがキューに入れられている場合、呼び出しを選択することがありますが、Releaseこれは多くの場合、設計上の問題を示しています。

于 2011-06-10T19:09:39.743 に答える
5

慣用的な使い方は

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によると、決して を呼び出すべきではありません。実際、は とまったく同じです。つまり、 の「安全な」バージョンです。ポインターがたまたま. [これをテストするには、プライベート フィールドをフォーム クラスに追加してから、OnCreate (たとえば) vs.を試してください。]Freeif Self <> nil then Destroy;DestroynilFBitmap: TBitmapFBitmap.FreeFBitmap.Destroy

上記のアプローチを使用してフォームを作成するFreeと、フォーム クラスで奇妙なことを行わない限り、完全に安全です。

ただし、CreateForm(TForm2, Form2)フォームを作成し、フォームオブジェクトをグローバルインスタンス変数に保存するために使用しForm2、すぐに解放しない場合[たとえば、ウィンドウを非モーダルな方法でメインフォームの隣に貼り付けたい場合]のRelease代わりに使用する必要がありFreeます。ドキュメントから、

Release は、フォームのすべてのイベント ハンドラーとフォーム上のコンポーネントのイベント ハンドラーの実行が完了するまで、フォームを破棄しません。Release は、フォームがリリースされる前に、フォームのイベント キュー内のすべてのメッセージが処理されることも保証します。フォームまたはその子のイベント ハンドラは、Free (Delphi) または delete (C++) の代わりに Release を使用する必要があります。そうしないと、メモリアクセスエラーが発生する可能性があります。

FreeOnReleaseフォームとは特に関係ありません。ドキュメントから:

FreeOnRelease を直接呼び出す必要はありません。

于 2011-06-10T18:52:17.653 に答える