オブジェクトメモリの割り当てとリサイクルについて
ここに DL レジスタを配置するアイデアがあるかどうかはわかりません。そうでない場合は、考えてみてください。実際、次のコード (1) の前に MOV dl, 1 というコード行がありますが、なぜこのようになるのでしょうか? 理由はそれほど単純ではなく、コードの再利用です。ここでのdlレジスタの使い方については、Delphiのヘルプに紹介がありますので、気長に探して見つければ達人です。これは学習、いや、釣り方を学ぶことであり、魚を求めることではありません。ボーランド氏はこう言いました。「フラグを格納するために dl レジスタを使用します。値が 1 の場合、オブジェクトを作成します。そうでない場合は、オブジェクトを作成しません。少し迷っている場合は、もう一度考えてください。」また。まだ目を開けていない場合は、次のコード (2) を見てください。見つからなかったとは言わないでください、咳き込んで、何が起こっているのですか、私はばかげた話を続けています、私はしないことを約束しますもう一度言ってください。
{コード(1)
テストDL、DL
jz +$08
ESPを追加、-$10
@ClassCreate を呼び出します }
{///コード (2)
手順Tapplication.CreateForm(InstanceClass: TComponentClass; var Reference);
変数
インスタンス: TComponent;
始める
//////// インスタンス := TComponent(InstanceClass.NewInstance);
TComponent(参照) := インスタンス;
試す
//////// Instance.Create(Self);
を除外する
TComponent(参照) := nil;
上げる;
終わり;
if (FMainForm = nil) かつ (インスタンスが TForm)
始める
TForm(インスタンス).HandleNeeded;
FMainForm := TForm(インスタンス);
終わり;
終わり;
}
この場合、つまり、作成されたクラスのインスタンスが初めて呼び出されるときに、Delphi はコード (1) を呼び出します。その後、誰かが Create メソッドを呼び出す必要がある場合、私、いいえ、それはコンパイラです。この MOV DL のように、 0 なので、コード (1) の判定 0 ジャンプ命令は、行くべき場所に移動します (なぜまたナンセンスなことを言っているのですか? 最後に約束します。) 実際、ここでの Create メソッドは単なるメソッドです。通常のメソッド、および 、Create メソッドまたは NewInstance メソッドの最初の呼び出しが、このメッセージを送信するクラスであることにも注意してください (このメッセージは、 Windows メッセージ、このメッセージは別のメッセージではありません、ははは、またナンセンスです、本当に最後です、本当です、ここのメッセージが理解できない場合は、オブジェクト指向とモデリングの知識を注意深く学習してください) を呼び出してください。 Create メソッドは確立されたオブジェクト Instance.Create(Self) です。当然、dl レジスタの値は変更されています。
さて、時間がありませんので、最後に国旗について付け加えておきます(台湾の翻訳方法、この言葉は良いと思います。今後の手間を省くためにも使用することをお勧めします)。このDLレジスタの使い方も、よく考えたら1から6まで何も変わっていないというべきです。 ちなみに、これはDelphiのHBデザイナーがキャラクターであることの証明でもあります。 . もちろん、比較することはできません。ははは、また行きます、わかりました、話はやめます。ああ、最後に、TObject.Create メソッドは決して空のメソッドではないことを思い出してから考えてください。
そうですね、その他のことは、実際に行って見てください。
「ここから出て行け、私はそれを見て考えたい、そしてあなたのナンセンスは要らない!誰かが笑っていた!」 :)
さよなら
コンパイラがオブジェクトにメモリを割り当てるとき、コンパイラが提供するサポートは、コンストラクターを呼び出す前に次のアセンブリ コード行を挿入することです。
テストDL、DL
jz +$08
ESPを追加、-$10
call @ClassCreate // このコード行に注目してください
上記のコードの最後の行は、system.pas ファイルの 8949 行目で _ClassCreate 関数を呼び出します (Delphi 6 の対象)。この関数は、各オブジェクトに適切なメモリを具体的に割り当てます。メモリ割り当てが完了すると、クラスのコンストラクターが呼び出され、データ メンバーが初期化されます。その後、コンパイラは次のアセンブリ コード行を挿入します。
テストDL、DL
jz +$0f
@AfterConstruction を呼び出します
dWord ptr fs をポップ:[$00000000]
ESP を追加、$0c
主な仕事は、各オブジェクト インスタンスの AfterConstruction を呼び出すことです。この呼び出しは、C++Builder 用に予約されています。
同様に、オブジェクトを破棄するときは、最初にクラスのデストラクターを呼び出して、オブジェクトによって要求されたリソースを解放する必要があります。その後、オブジェクト自体が占有するメモリ空間がリサイクルされ、コンパイラがデストラクターを呼び出した後に次のアセンブリ コードを挿入することでこの作業が完了します。
@BeforeDestruction を呼び出す
テストDL、DL
ジェイル +$05
@ClassDestroy に電話してください
これらのコードによって行われる作業は、オブジェクトの構築およびメモリの割り当て時に行われる処理に対応しており、主に system.pas の 8997 行目で _ClassDestroy 関数を呼び出します。
コンストラクターとデストラクター
コンストラクターを定義するには、Constructor キーワードを使用します。慣例により、コンストラクターの名前は Create です (もちろん他の名前も使用できますが、これは決して良い設計ではありません)。のように:
タイプ
TMyFamily = class // ファミリ用に定義されたクラス
プライベート
FMyFatherName : String; あなたの父親の名前
FMyMotherName : String; あなたの母親の名前
… // あなたの家族の他のメンバー
公共
コンストラクター Create(strFatherName, strMotherName : String);
…… // 他のメソッド
終わり;
クラスにコンストラクターを提供しない場合、そのオブジェクトは作成できるのかと疑問に思うかもしれません。答えは「はい」です。理由は前述しましたが、オブジェクト自体が占有するメモリの割り当てはコンパイラによって完了されます。また、Object Pascal では、すべてのクラス (TObject クラス自体を除く) が TObject クラスから派生するため、コンパイラーは TObject.Create() コンストラクターを呼び出しますが、この関数は空の関数であり、TMyFamily クラスには影響しません。データ メンバー (FMyFatherName、FMyMotherName) が初期化されると、TObject.Create() は父親または母親をまったく認識しないため、それらは自動的に空の文字列 (つまり '') にクリアされます。
オブジェクトを作成するとき、コンストラクターは次の形式で直接呼び出されます。
MyFamilyObject := TMyFamily.Create('Zhang', 'Li');
デストラクターを定義するには、Destructor キーワードを使用します。慣例により、デストラクターには Destroy という名前が付けられます。のように:
タイプ
TMyClass = クラス
公共
デストラクター Destroy();
終わり;
デストラクター宣言の最後に override ステートメントを追加する理由は、ポリモーフィズムの場合にオブジェクトを正しく破棄できるようにするためです (ポリモーフィズムについてはセクション 2.4 で詳しく説明します)。 override キーワードを追加しない場合、コンパイラは「メソッド 'Destroy' は基本型 'TObject' の仮想メソッドを隠します」のような警告を出します。この警告は、定義した Destroy が基本クラスの仮想メソッド TObject.Destroy() を非表示にすることを意味します。この場合、ポリモーフィックな状況ではオブジェクトを正しく破棄できません。
注: デストラクターは、override ステートメントを使用して宣言する必要があります。
同様に、クラス内に解放する必要がある特別なリソースがない場合は、デストラクターを定義する必要はありません。ただし、オブジェクトを破棄するときは、Destroy() を直接呼び出すのではなく、オブジェクトの Free() メソッドを呼び出す必要があります。
MyFamilyObject.Free();
これは、Free() メソッドがオブジェクト自体が nil かどうかを判断し、nil でない場合は安全性を高めるためにオブジェクトの Destroy() が呼び出されるからです。これを行うためのより安全な方法がある今、それを行わない理由は確かにありません。
注: オブジェクトに対して Destroy() を直接呼び出さないでください。代わりに Free() を呼び出してください。
このことから、Object Pascal では、オブジェクトによって適用されたリソースの割り当てと解放にのみ注意を払う必要があり、オブジェクト自体が占有するスペースを気にする必要はない、と結論付けることができます。