バイトを格納するレコードを使用して、プログラムの他の部分にあるオブジェクトのフィールドにアクセスし、同じ名前の関数を使用して別のレコードのフィールドにアクセスするエレガントな方法を見つけようとしています。レコードのフィールド。
TAilmentP = Record // actually a number but acts like a pointer
private
Ordinal: Byte;
public
function Name: String; inline;
function Description: String; inline;
class operator Implicit (const Number: Byte): TAilmentP; inline;
End;
TSkill = Class
Name: String;
Power: Word;
Ailment: TAilmentP;
End;
class operator TAilmentP.Implicit (const Number: Byte): TAilmentP;
begin
Result.Ordinal := Number;
ShowMessage (IntToStr (Integer (@Result))); // for release builds
end;
function StrToAilment (const S: String): TAilmentP; // inside same unit
var i: Byte;
begin
for i := 0 to Length (Ailments) - 1 do
if Ailments [i].Name = S then
begin
ShowMessage (IntToStr (Integer (@Result))); // for release builds
Result := i; // uses the Implicit operator
Exit;
end;
raise Exception.Create ('"' + S + '" is not a valid Ailment"');
end;
ここで、変換演算子をオーバーロードして作業を楽にしようとしていたので、バイトを TAilmentP オブジェクトに割り当てようとすると、それが Ordinal フィールドに割り当てられます。ただし、私が確認したように、暗黙の「演算子」への呼び出しは戻り値の新しい TAilmentP オブジェクトを作成し、そのビジネスを行い、値を返し、アドレスが異なるため、それを呼び出したオブジェクトにバイトごとのコピーを作成します。
正直なところ、私のコードはこのメソッドをかなり頻繁に呼び出しており、オブジェクトの Ordinal フィールドに値を直接代入するよりも遅いようです。
ANYメソッド/関数を使用して、プログラムに実際に値をフィールドに直接割り当てる方法はありますか? インライン化しても機能しないようです。オブジェクト自体ではなく、(レコード) 変数への参照を返す方法はありますか? 最後に (トピックから少し外れて申し訳ありません)、なぜ演算子のオーバーロードは静的関数を介して行われるのでしょうか? それらを逆参照せずにオブジェクトフィールドにアクセスできるので、それらをインスタンスメソッドにすると高速になりますか? これは、ここと私のコードの他の部分で本当に便利です。
[編集] これは、すべての最適化が有効で、デバッグ機能がない (ブレークポイントの「デバッグ情報」でさえない) Implicit オペレーターのアセンブラー コードです。
add al, [eax] /* function entry */
push ecx
mov [esp], al /* copies Byte parameter to memory */
mov eax, [esp] /* copies stored Byte back to register; function exit */
pop edx
ret
さらにおもしろいのは、次の関数の起動時に mov eax, eax 命令があることです。今では本当に便利に見えます。:P そうそう、私の Implicit 演算子もインライン化されませんでした。
[esp] は Result 変数であると確信しています。割り当て先とは異なるアドレスを持っているからです。最適化をオフにすると、[esp] は [ebp-$01] (割り当て先) と [ebp-$02] (Byte パラメーター) に置き換えられ、[ebp-$02] を AL に移動する命令がもう 1 つ追加されます (その後、 [ebp-$01] に配置します)、冗長な mov 命令は [epb-$02] にまだあります。
何か間違ったことをしていますか、それとも Delphi には戻り値の最適化がありませんか?