2017-11-27 173 views
4

Integerstringに変換すると、IntToStr()Integer.ToString()の基本的な違いは何ですか?どちらが速いの?DelphiコンパイラのIntToStr()とInteger.ToString()の違いは?

var 
    VarInt: integer; 
    VarStr: string; 
begin 
    VarInt := 5; 
    VarStr := IntToStr(VarInt); 
    VarStr := VarInt.ToString; 
end; 
+2

違いはありません。 ToStringはインライン展開されているため、コンパイラは本質的に同じ結果を生成します。 – Victoria

+0

'VarStr:=(VarInt + 1).ToString'と組み合わせると同じ結果とスピードです –

+1

はい。どちらの場合も、最初に式 'VarInt + 1'を評価しなければなりません。 – Victoria

答えて

9

免責事項

コンパイラによって生成されるコード:以下のテキストのみをインライン化し、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として報告されています。

続ける...

+0

興味深いことに、シアトルでは、ランタイムパッケージにリンクすると両方の命令が100%同一になります。そうでなければ、私は10.1と同じ結果を得る –

+0

いいえ、彼らは、2つの呼び出しのアドレスを見ていない。 2番目の関数は、非インラインヘルパー関数を呼び出します。 –

+0

確かに、私はそれを逃した。しかし、UStrLAsgの部分は削除してください。 –

3

違いはありません。

Int.ToStringはそうのように定義されています。それがインライン化され

function TIntHelper.ToString: string; inline; 
begin 
    Result := IntToStr(Self); 
end; 

ので、それだけでIntToStr(Int)に変換します。

var.actionのメソッドが追加され、JavaおよびC#プログラマーにRTL(Runtime Library)をより使いやすくしました。人々がJavaにさらされている可能性が高いモバイルプラットフォームに特に関係します。

このようにすることの大きな利点は、機能がはるかに発見可能であることです。 VarInt.と入力するだけで自動補完機能が利用可能なすべてのオプションを表示します。すでにIntToStrについて知らない場合は、それを見つけるのは難しいです。

+0

さらに、文字列の場合、.IndexOf、.SubStringなどはPos()やCopy()よりもはるかに簡単です。 –

関連する問題