zoukankan      html  css  js  c++  java
  • Delphi 究竟产生了几个String对象的问题

    技术交流,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个变量 指向地址进行比较的.
    而这个里面因为地址是相同的,所以直接返回了,还没有对地址里面内容进行比较.

  • 相关阅读:
    (转)js的左右滑动触屏事件
    (转)Document对象内容集合
    AppCan相关网站
    (转)iOS应用程序生命周期(前后台切换,应用的各种状态)详解
    (转)深入浅出 iOS 之生命周期
    (转)iphone数据存储之-- Core Data的使用
    (转)xcode5.0.2下国际化图文解说
    (转)IOS之Info.plist文件简介
    Note_Master-Detail Application(iOS template)_06_ YJYDetailViewController.h
    Note_Master-Detail Application(iOS template)_07_ YJYDetailViewController.m
  • 原文地址:https://www.cnblogs.com/huangjacky/p/1664243.html
Copyright © 2011-2022 走看看