IntToStr()和Integer.ToString()之间的Delphi编译器区别? [英] Delphi compiler difference between IntToStr() and Integer.ToString()?

查看:224
本文介绍了IntToStr()和Integer.ToString()之间的Delphi编译器区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

转换<$ c时, IntToStr() Integer.ToString()的基本区别是什么? $ c>整数到字符串。哪个更快?

What is the basic difference between IntToStr() and Integer.ToString() when converting an Integer to a string. Which one is faster?

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


推荐答案

免责声明:文本包含仅适用于Delphi 10.2.1(以及10.2.2)的详细信息,这似乎使内联和RVO变得更糟:

Disclaimer: The following text contains details that only apply to Delphi 10.2.1 (and also 10.2.2) which seems to have made something worse about inlining and RVO:

当您进入反汇编窗口时可以很容易地看到编译器的确有所不同(无论编译器版本如何)。

The code produced by the compiler indeed differs (regardless the compiler version) as you can easily see when looking into the disassembly window.

让我们执行以下例程:

procedure Main;
var
  i: Integer;
  s: string;
begin
  i := 0;
  s := IntToStr(i);
  s := i.ToString;
end;

现在让我们运行它并查看反汇编窗口以检查编译器生成的代码:

Now let's run this and look into the disassembly window to check the code the compiler produced:

这是使用Delphi 10.1的功能:

This is what you got with Delphi 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)所得到的:

And this is what you get with 10.2.1 (and also 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

现在,百万美元的问题是,那里所有额外的指令是什么?!

Now the million dollar question is, what is all that extra instructions there?!

在两个编译器中都能看到的额外指令是缺少所谓的返回值优化的结果。如您所知,编译器会将托管类型(如字符串)的函数结果视为隐藏的var参数。现在,当编译器执行内联时,它不会消除此参数,而是将 s 变量直接传递给 IntToStr 直接调用时会执行。而是保留一个临时变量,该变量用于传递给 IntToStr ,然后将其分配给 s (这是调用@UStrLAsg ,您会在 IntToStr 调用之后看到3行。)

The extra instructions that you can see in both compilers is the result of missing so called return value optimization. As you might know the compiler treats results of functions that are of a managed type (like string) as hidden var parameter. Now when the compiler does the inlining it does not eliminate this parameter and directly passes the s variable to the IntToStr as it does when directly calling it. It rather reserves a temporary variable that it uses to pass to the IntToStr and then after that assigns that variable to s (that's the call @UStrLAsg you see there 3 lines after the IntToStr call).

如上所述,在10.2或10.2.1中似乎存在回归,它们在内联调用之后立即更改了有关临时变量清除的内容(这是此之前和之后的额外说明)。

As I mentioned above there seems to be a regression in 10.2 or 10.2.1 where they changed something about temporary variable cleanup right after the inlined call (that's the extra instructions before and after that).

报告为 RSP-19439

待续...

这篇关于IntToStr()和Integer.ToString()之间的Delphi编译器区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆