• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Delphi-究竟产生了几个String对象的问题

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

技术交流,DH讲解.

这个是在CSDN上面看见的问题.我说说自己的想法.

procedure TForm1.btn1Click(Sender: TObject);
var
  Str:String;
begin
  Str:='abc' ;
   
  Str:=str+'d';
 
  str:=copy(Str,1,3);
 
  str:=UpperCase(str);
end;
问题1答案:2010下
Unit4.pas.29: begin 005144E0 55 push ebp 005144E1 8BEC mov ebp,esp 005144E3 6A00 push $00 005144E5 6A00 push $00 005144E7 33C0 xor eax,eax 005144E9 55 push ebp 005144EA 6856455100 push $00514556 005144EF 64FF30 push dword ptr fs:[eax] 005144F2 648920 mov fs:[eax],esp Unit4.pas.30: Str:='abc' ; 005144F5 8D45FC lea eax,[ebp-$04] 005144F8 BA70455100 mov edx,$00514570 //这块内存中存放的是 abc 字符串对象 005144FD E8E631EFFF call @UStrLAsg //跟进这个函数,由于abc块处本来就是Unicode的,所以不需要转换,只是引用次数加一,也就是这里是 编译器一开始就产生了一个 abc 字符串对象 Unit4.pas.32: Str:=str+'d'; 00514502 8D45FC lea eax,[ebp-$04] 00514505 BA84455100 mov edx,$00514584 //类似这里是一个'd'的字符串对象,总共出现2个了 0051450A E8A935EFFF call @UStrCat //会对调用UStrSetLength,eax是abc地址,edx是4,也就是先给abc扩容,而这个函数里面调用了NewUnicodeString,会新产生一个abc字符串对象空间,然后在这个对象空间上用mov把d移到abc上去,形成abcd,到现在出现了3个字符串对象了. Unit4.pas.34: str:=copy(Str,1,3); 0051450F 8D45FC lea eax,[ebp-$04] //从这一句我们也可以看见局部变量的指针也改变位置了 00514512 50 push eax 00514513 B903000000 mov ecx,$00000003 00514518 BA01000000 mov edx,$00000001 0051451D 8B45FC mov eax,[ebp-$04] 00514520 E8BF38EFFF call @UStrCopy //先增加一次被复制字符串的引用次数,然后在UStrFromPWCharLen中调用NewUnicodeString申请一个空间为3的字符串对象,地址$00F2e02c,第4个了哟,最后设置好偏移后,用Mov函数将abc移到这个空间去 Unit4.pas.36: str:=UpperCase(str); 00514525 8D55F8 lea edx,[ebp-$08] //这个地址里面是什么?应该是返回值,现在还是$00000000 00514528 8B45FC mov eax,[ebp-$04] //这里能看到Str变量的指针又变化了 0051452B E880CFEFFF call UpperCase //再次调用UStrSetLength新分配一个长度为3的字符串对象空间,第5个了哟.然后吧这个字符串里面的字符大写. 00514530 8B55F8 mov edx,[ebp-$08] 00514533 8D45FC lea eax,[ebp-$04] 00514536 E8AD31EFFF call @UStrLAsg //这里比对是否是Unicode,因为是,所以基本没有操作 Unit4.pas.37: end; 0051453B 33C0 xor eax,eax 0051453D 5A pop edx 0051453E 59 pop ecx 0051453F 59 pop ecx 00514540 648910 mov fs:[eax],edx 00514543 685D455100 push $0051455d 00514548 8D45F8 lea eax,[ebp-$08] 0051454B BA02000000 mov edx,$00000002 00514550 E83731EFFF call @UStrArrayClr 00514555 C3 ret

但是abc 和 d 那两个字符串是编译的时候就被Delphi给写进去了,也就是编译期产生的,不是运行的时候产生的.运行时候产生的字符串就只有3个

procedure TForm1.btn1Click(Sender: TObject);
var
  Str:String;
begin
  Str:='abc'+'d'+'f' ;
end;
问题2答案:
Unit4.pas.29: begin
005144E0 55               push ebp
005144E1 8BEC             mov ebp,esp
005144E3 6A00             push $00
005144E5 33C0             xor eax,eax
005144E7 55               push ebp
005144E8 6816455100       push $00514516
005144ED 64FF30           push dword ptr fs:[eax]
005144F0 648920           mov fs:[eax],esp
Unit4.pas.30: Str:='abc'+'d'+'f' ;
005144F3 8D45FC           lea eax,[ebp-$04]
005144F6 BA2C455100       mov edx,$0051452c //Delphi编译器直接生成了abcdf字符串对象
005144FB E8E831EFFF       call @UStrLAsg 
Unit4.pas.31: end;
00514500 33C0             xor eax,eax
00514502 5A               pop edx
00514503 59               pop ecx
00514504 59               pop ecx
00514505 648910           mov fs:[eax],edx
00514508 681D455100       push $0051451d
0051450D 8D45FC           lea eax,[ebp-$04]
00514510 E86F31EFFF       call @UStrClr
00514515 C3               ret 

答案就是0个了,abcdf是编译时候产生的,运行的时候只是把str指向这个编译时候就有了的内存.

procedure TForm1.btn1Click(Sender: TObject);
var
  Str,Str1:String;
begin
  Str:='abc'  ;
  Str1:='abc';
  if (Str=Str1) then
  ShowMessage('相同')
  else
  ShowMessage('不相同') 
end;
问题3答案:
Unit4.pas.30: Str:='abc'  ;
00523AF5 8D45FC           lea eax,[ebp-$04]
00523AF8 BA643B5200       mov edx,$00523b64
00523AFD E8263CEEFF       call @UStrLAsg
Unit4.pas.31: Str1:='abc';
00523B02 8D45F8           lea eax,[ebp-$08]
00523B05 BA643B5200       mov edx,$00523b64
00523B0A E8193CEEFF       call @UStrLAsg
Unit4.pas.32: if (Str=Str1) then
00523B0F 8B45FC           mov eax,[ebp-$04]
00523B12 8B55F8           mov edx,[ebp-$08] //2个局部变量都指向同一个内存地址,但是比较的时候用的是UStrEqual函数,所以还得看这个函数是怎么比较的
00523B15 E8A242EEFF       call @UStrEqual //这个函数一进来是直接比较指针地址,也就是相等的了,就返回了
00523B1A 750C             jnz $00523b28
Unit4.pas.33: ShowMessage('相同')
00523B1C B8783B5200       mov eax,$00523b78
00523B21 E80A4EFBFF       call ShowMessage
00523B26 EB0A             jmp $00523b32
Unit4.pas.35: ShowMessage('不相同') 
00523B28 B88C3B5200       mov eax,$00523b8c
00523B2D E8FE4DFBFF       call ShowMessage
Unit4.pas.36: end;
00523B32 33C0             xor eax,eax

从上面看出来,直接是对栈上面2个变量 指向地址进行比较的.
而这个里面因为地址是相同的,所以直接返回了,还没有对地址里面内容进行比较.


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
[控件][IrDA,USB,bluetoothCOMports]nrCommLibPro8.30forDelphi&C++Builder发布时间:2022-07-18
下一篇:
delphi设置表格样式。发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap