to JGTM2000:精,妙,好。 to gigi2000: 分数非JGTM2000莫属,加分吧。TO JGTM2000: 您是不是常用[email protected]这个信箱?
To gigi2000: 如果还有什么困惑可以继续提出来,大家帮你解答。 To keboy, netsong: Thanks for your appreciation. :) I often check my mailbox @sina.com, so write to me if you need help. My pleasure. :)
char就是一个一个的字符了,
pchar就是c++中的string,以一个#0结尾.存在的原因如xiaohuilau所讲.
不知道我记得对不对,
设s、c、p分别为string、char、pchar类型,他们的值都为'hello';
1、s[1]值为'h',c[1]值为'e',p[1]值为'e';
2、p:=c,s:=c是正确的,p:=s错误的;
3、他们分别为字符串类型、数组类型、指针类型;
则有PChar(s)^ = 'C',(PChar(s)+1)^='S',……(PChar(s)+4)^=#0。
且:PInteger(Integer(Pointer(s))-1*sizeof(DWORD))^=length(s)
和:PInteger(Integer(Pointer(s))-2*sizeof(DWORD))^=refcount(s)可视化一下就是:
[RefCount: DWORD][Length: DWORD]^['C']['S']['D']['N'][#0]
(^处即为s所指内存地址)可以看到string在s之后的内存布局同PChar完全一致,都是ASCIIZ标准的字串,因此任何string类型的变量都可以通过强制类型转换的语法欺骗编译器的强类型检查而作为PChar直接使用,如: PChar(s)。而且由于字串的长度存放在偏移-4处,因此求字串长度的时候速度极快,因为length(s) = PInteger(Integer(Pointer(s))-4)^,不用像PChar和array那样从头数到尾直到#0。那引用计数是干哈的呢?首先要明确一点,Delphi对于string是从堆中自动分配和释放内存,分配好说,但是什么时候释放呢?如果你了解COM的引用计数原理就知道,通过维护refCount系统就能够确定可以安全释放对象的时机了。因为Delphi对于string类型的字串使用了copy-on-write技术,因此如果简单的两个string都包含相同的内容,则实际上内存中仅有一份拷贝。如:
s1 := 'I love Delphi'; // line 1
s2 := s1; // line 2
s1 := s1 + '!'; // line 3
在第一行,Delphi将为s1分配内存并设定好负偏移处的长度信息与引用计数(初始为1);在第二行,事实上没有任何的内存分配操作,s2简单的被赋予s1的指针信息,同时他们指向的字串的引用计数+1(事实上Delphi程序内部还有一张表来记录这些引用信息和变量实例的关系);在第三行,s1进行了改变,根据内部的逻辑规则,Delphi将自动分配新的内存并实际拷贝s1+'!'的内容到新的内存中,然后改变s1的地址和s2指向字串的引用计数就搞定了。这就是所谓的copy-on-write。你说了,这没什么用啊,哪儿这么多直接的赋值啊?其实像返回字串的函数这类情况都能发挥copy-on-write的好处,经济、快速。综合一下,在Delphi编程中应该尽可能的使用string类型简化代码、减少出错并提高程序的运行效率。在调用C或者其他应用PChar的场合可以直接拿PChar(string)来用,不存在效率问题(因为只是强制转换而已)。字符数组主要用于定宽字串和定义结构时候用,不过只有下标为0且数组成员类型为char的array才和PChar兼容。
佩服,佩服(事实上,如果你能充分的理解string,你就会赞叹Delphi的精妙了),精辟之极.
gigi2000,你再不给分,对不起他老人家了;
你老是不是在北京?真想跟你学学。
my e_mail : [email protected]
难道你还比明白吗
这么多人回答
我看已没什么可回答的了
to gigi2000: 分数非JGTM2000莫属,加分吧。TO JGTM2000: 您是不是常用[email protected]这个信箱?
To keboy, netsong: Thanks for your appreciation. :) I often check my mailbox @sina.com, so write to me if you need help. My pleasure. :)