又是一个关于String生成几个对象的问题

liangpei2008 2010-01-30 09:05:17
加精
在Java版块看到这样的问题太多了,联想一下Delphi的String类型,我也出几个题目让大家娱乐一下(最好先根据原理想一下再看BASM)!


本贴例题,纯属虚构。
如有雷同,纯属巧合。

相关奖励:
一等奖的网友可以与Delphi版块的华仔一起赏花赏月,毫不夸张地说,这样的奖励在CSDN其它版块有没有、有没有!?
赶快敲起你手中的按键,回答问题吧......

问题1:在下述过程被调用时,共有多少个字符串对象被创建,并说明原因!

procedure TForm1.btn1Click(Sender: TObject);
var
Str:String;
begin
Str:='abc' ;

Str:=str+'d';

str:=copy(Str,1,3);

str:=UpperCase(str);
end;




问题2:运行下述语句会产生几个String对象,并说明原因!

procedure TForm1.btn1Click(Sender: TObject);
var
Str:String;
begin
Str:='abc'+'d'+'f' ;
end;





问题3:运行下述语句中的Str=Str1,是栈指针的比较还是值的比较,并说明原因!!

procedure TForm1.btn1Click(Sender: TObject);
var
Str,Str1:String;
begin
Str:='abc' ;
Str1:='abc';
if (Str=Str1) then
ShowMessage('相同')
else
ShowMessage('不相同')
end;



问题4:下述二个过程中创建的String对象个数是否相同,为什么?

procedure TForm1.btn1Click(Sender: TObject);
var
Str,Str1 :String;
begin
Str:='abc' ;
Str1:=Str+'d';
end;

procedure TForm1.btn2Click(Sender: TObject);
const
str='abc';
var
str1:string;
begin
Str1:=Str+'d';
end;



问题5:运行下述语句会生成多少个字符串对象!!

procedure TForm1.btn1Click(Sender: TObject);
var
Str:String;
i:Integer;
begin
for i:=0 to 9 do
Str:=Str+'OK'
end;
...全文
2657 124 打赏 收藏 转发到动态 举报
写回复
用AI写文章
124 条回复
切换为时间正序
请发表友善的回复…
发表回复
wafer_lee 2010-02-17
  • 打赏
  • 举报
回复
学习是一种美德。。。谅解。
book_manlan 2010-02-08
  • 打赏
  • 举报
回复
支持,帮你定一下
ywb888 2010-02-06
  • 打赏
  • 举报
回复
丢开DELPHI很久了,原来学习的就很不深入,今天学习了。
tuo_li 2010-02-06
  • 打赏
  • 举报
回复
学习了,顶完在看
嘿呀土豆 2010-02-06
  • 打赏
  • 举报
回复
。。。
linghengmao 2010-02-05
  • 打赏
  • 举报
回复
学习来了!
huangjacky 2010-02-05
  • 打赏
  • 举报
回复
2010
问题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个变量 指向地址进行比较的.
而这个里面因为地址是相同的,所以直接返回了,还没有对地址里面内容进行比较.
huangjacky 2010-02-05
  • 打赏
  • 举报
回复
2010
问题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

所以这里只产生了一个字符串对象空间
huangjacky 2010-02-05
  • 打赏
  • 举报
回复
2010
问题1

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


从上面的分析,应该中间产生了5个字符串对象空间.
谢谢
wxieyang 2010-02-05
  • 打赏
  • 举报
回复
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3251928
这是大富翁论坛关于 Delphi 的 String 的 copy-on-write 机制的讨论。
挺长,不粘贴过来了,有兴趣的可以去看看
ygxdxxnyll 2010-02-05
  • 打赏
  • 举报
回复
mark下,下次继续关注
「已注销」 2010-02-05
  • 打赏
  • 举报
回复
占个座,有空来学习
dalezhu 2010-02-05
  • 打赏
  • 举报
回复
ding
cicelyq 2010-02-04
  • 打赏
  • 举报
回复
学习了
DelphiAaron 2010-02-04
  • 打赏
  • 举报
回复
Delphi之所以用起來很爽,就是因為不用關心這些不必要關心的東西。
无条件为你 2010-02-04
  • 打赏
  • 举报
回复
小声问一下:华仔 是男是女?
MournIA 2010-02-04
  • 打赏
  • 举报
回复
oo
stonebeauty 2010-02-03
  • 打赏
  • 举报
回复
string dim as new .asdf
jack914 2010-02-03
  • 打赏
  • 举报
回复
顶分吧。。
guyuxuelang 2010-02-03
  • 打赏
  • 举报
回复
我还以为是java的String呢,这个不懂啊
加载更多回复(100)

2,495

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 数据库相关
社区管理员
  • 数据库相关社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧