Delphi编译器IntToStr()和Integer.ToString()之间的区别?

时间:2017-11-27 18:51:12

标签: delphi delphi-xe delphi-10.2-tokyo

IntToStr()转换为Integer.ToString()时,Integerstring之间的基本区别是什么?哪一个更快?

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

2 个答案:

答案 0 :(得分:9)

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

编译器生成的代码确实不同(无论编译器版本如何),因为您在查看反汇编窗口时可以轻松看到。

让我们来看看这个例程:

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

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

这是您使用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):

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(即call @UStrLAsg,您在IntToStr之后看到3行呼叫)。

正如我上面提到的,在10.2或10.2.1中似乎有一个回归,他们在内联调用之后改变了一些临时变量清理(这是之前和之后的额外指令)。

报告为RSP-19439

继续......

答案 1 :(得分:3)

没有区别。

Int.ToString的定义如下:

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

因为它是内联的,所以它只会转换为IntToStr(Int)

添加了var.action方法,使运行时库(RTL)更适合Java和C#程序员。这对于人们可能接触过Java的移动平台尤为重要。

这样做的一个主要好处是功能更容易被发现。您只需输入VarInt.,自动完成功能就会显示所有可用选项。如果你不知道IntToStr已经很难找到它。