免責事項:
コンパイラによって生成されるコード:以下のテキストのみをインライン化し、RVOについてより悪い何かを作っているようだデルファイ10.2.1(とも10.2.2)に適用されることを詳細が含まれています逆アセンブリウィンドウを調べるときに簡単に見られるように(コンパイラのバージョンに関係なく)実際には異なります。
このルーチンを取ることができます:
procedure Main;
var
i: Integer;
s: string;
begin
i := 0;
s := IntToStr(i);
s := i.ToString;
end;
今度は、これを実行すると、コンパイラが生成するコードをチェックするために解体ウィンドウに見てみましょう:
これは、あなたがデルファイ10.1で得たものである:
Project1.dpr.14: s := IntToStr(i);
00419810 8D55F8 lea edx,[ebp-$08]
00419813 8B45FC mov eax,[ebp-$04]
00419816 E80DA4FFFF call IntToStr
Project1.dpr.15: s := i.ToString;
0041981B 8D55F4 lea edx,[ebp-$0c]
0041981E 8B45FC mov eax,[ebp-$04]
00419821 E802A4FFFF call IntToStr
00419826 8D45F8 lea eax,[ebp-$08]
00419829 8B55F4 mov edx,[ebp-$0c]
0041982C E843D2FEFF call @UStrLAsg
これは10.2.1(および10.2.2)で得られるものです。
Project1.dpr.14: s := IntToStr(i);
00419B04 8D55F8 lea edx,[ebp-$08]
00419B07 8B45FC mov eax,[ebp-$04]
00419B0A E8C5A2FFFF call IntToStr
Project1.dpr.15: s := i.ToString;
00419B0F 33C0 xor eax,eax
00419B11 55 push ebp
00419B12 68499B4100 push $00419b49
00419B17 64FF30 push dword ptr fs:[eax]
00419B1A 648920 mov fs:[eax],esp
00419B1D 8D55F4 lea edx,[ebp-$0c]
00419B20 8B45FC mov eax,[ebp-$04]
00419B23 E8ACA2FFFF call IntToStr
00419B28 8D45F8 lea eax,[ebp-$08]
00419B2B 8B55F4 mov edx,[ebp-$0c]
00419B2E E805D0FEFF call @UStrLAsg
00419B33 33C0 xor eax,eax
00419B35 5A pop edx
00419B36 59 pop ecx
00419B37 59 pop ecx
00419B38 648910 mov fs:[eax],edx
00419B3B 68509B4100 push $00419b50
00419B40 8D45F4 lea eax,[ebp-$0c]
00419B43 E8D4CCFEFF call @UStrClr
00419B48 C3 ret
00419B49 E9CEC3FEFF jmp @HandleFinally
00419B4E EBF0 jmp $00419b40
今、何百万ドルもの質問がありますが、その余分な指示は何ですか?
両方のコンパイラで表示される余分な指示は、いわゆる戻り値の最適化が欠落した結果です。コンパイラは、管理された型(文字列など)の関数の結果を隠しvarパラメータとして扱います。コンパイラがインライン展開を実行したときに、このパラメータを削除せずに直接s
変数をIntToStr
に直接渡します。代わりにIntToStr
に渡すために使用する一時変数を予約してから、その変数をs
に割り当てます(これは呼び出しの後に3行表示されるcall @UStrLAsg
です)。
上記のように、10.2または10.2.1の回帰があるようですが、インラインコール直後の一時的な変数のクリーンナップに関する変更がありました(その前と後の追加の指示です)。
RSP-19439として報告されています。
続ける...
違いはありません。 ToStringはインライン展開されているため、コンパイラは本質的に同じ結果を生成します。 – Victoria
'VarStr:=(VarInt + 1).ToString'と組み合わせると同じ結果とスピードです –
はい。どちらの場合も、最初に式 'VarInt + 1'を評価しなければなりません。 – Victoria