17

GUIアプリケーションのこのコードは、コンパイルして実行します。

procedure TForm1.Button1Click(Sender: TObject);
begin
  Self := TForm1.Create(Owner);
end;

(Delphi 6および2009でテスト済み)

  • なぜ自己書き込み可能で読み取り専用ではないのですか?
  • これはどのような状況で役立ちますか?

編集:

  • これはDelphiPrismでも可能ですか?(そうだと思います。こちらをご覧ください

更新:自己割り当てを利用するDelphiアプリケーション/ライブラリ:

4

5 に答える 5

11

それはそれほど悪くはありません。Delphi 2009でテストしたところ、Selfパラメーターはconstセマンティクスを使用していないようですが、これは当然のことですが、 varセマンティクスも使用していないため、すべて変更できます。呼び出し元がオブジェクトに対して保持している参照を実際に失うことなく、メソッド内で必要です。それは非常に悪いことです。

その理由は、2つのうちの1つです。単純な見落とし、またはマルコが提案したこと:Selfをvarパラメーターに渡すことができるようにすること。

于 2009-05-02T12:24:01.937 に答える
7

たぶん、constまたはvarパラメーターへの受け渡しを許可しますか?

システムには:=記号の左側に自己がないため、これはアーティファクトである可能性があります。

于 2009-05-02T11:40:21.247 に答える
5

自己への割り当ては非常に非論理的で役に立たないため、この「機能」はおそらく見落としです。また、割り当て可能な定数と同様に、このような問題を修正するのは必ずしも簡単ではありません。

ここでの簡単なアドバイスは次のとおりです。それをしないでください。

于 2009-05-02T17:16:29.473 に答える
2

実際には、「Self」は、ヒープ内のオブジェクトを指すアドレスを格納するスタック上の場所への単なる名前参照です。この変数に読み取り専用を強制することは可能ですが、設計者はそうしないことに決めたようです。決定は恣意的だと​​思います。

これが便利な場合はわかりません。スタック内の値を変更するだけです。また、この値を変更すると、インスタンスのメンバーを参照するコードの動作がコンパイラのバージョン間で一貫しているという保証がないため、危険な場合があります。

更新:PatrickvLコメントへの返信

'変数'"Self"はスタックにありません(私の知る限り、スタックにはありません)。代わりに、その値は、オブジェクトメソッドが呼び出される直前にレジスタ(正確にはEAX)に格納されます。– </ p>

いいえ、Selfのメモリには実際のアドレスがあります。このコードを試して、自分の目で確かめてください。

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(IntToStr(Integer(@Self)));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  newform: TForm;
  p: ^Integer;
begin
  Self.Caption := 'TheOriginal';
  newform := TForm.Create(nil);
  try
    newform.Caption := 'TheNewOne';
    // The following two lines is, technically, the same as
    //   Self := newform;
    p := Pointer(@Self);
    p^ := Integer(newform);
    ShowMessage(Self.Caption);  // This will show 'TheNewOne' instead of 'TheOriginal'
  finally
    Self.Free; // Relax, this will free TheNewOne rather than TheOriginal
  end;
end;
于 2009-05-02T12:04:21.690 に答える
1

場合によっては、(アセンブリに頼らずに)メソッドを可能な限り最適化する場合、「Self」を「free」変数として(ab)使用できます。これは、スタックとの使用の違いを意味する場合があります。レジスタを使用します。

確かに、スタックの内容はおそらくCPUキャッシュにすでに存在しているため、アクセスは高速であるはずですが、レジスタはさらに高速です。

補足として:私がAmigaのMotorola 68000でプログラミングしていて、16個のデータと16個のアドレスレジスタの贅沢を持っていた日々をまだ逃しています...世界が限られた4個のレジスタで行くことを選んだとは信じられませんプロセッサの80x86ラインの!

そして最後に、Delphiのオプティマイザは実際にはそれほど最適化されていないため、Selfを使用することを選択することがあります。(少なくとも、さまざまなLLVMオプティマイザーで見られるトリックと比べると見劣りします。)もちろん、IMHOとYMMVです。

于 2010-03-30T11:49:33.093 に答える