300分提问引用计数(100分)

  • 主题发起人 主题发起人 liuchong
  • 开始时间 开始时间
L

liuchong

Unregistered / Unconfirmed
GUEST, unregistred user!
一:
var
S:string;
begin
S:='abc';//此时S的引用计数是多少?
end;

二:

procedure TForm1.btn1Click(Sender: TObject);
var
S:string;
begin
S:='abc';
edt1.Text:=IntToStr(Cardinal(S))+':'+IntToStr(Cardinal(@S[1]));
end;

procedure TForm1.btn2Click(Sender: TObject);
var
S:string;
begin
S:='abc';
edt1.Text:=IntToStr(Cardinal(@S[1]))+':'+IntToStr(Cardinal(S));
end;
这里用到的S[1]为读取操作,会不会改写引用计数?

三:
如果S会改写引用计数,那么下面两段代码怎么会有效率差异:
var
S:string;
I:Cardinal;
begin
S:='';
for I:=1 to 1000000 do
S:=S+'a';
end;

var
S:String;
I:Cardinal;
begin
SetLength(S,1000000);
for I:=1 to 1000000 do
S:='a';
end;





答对者可到下面地址领分:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3327037
 
跟计数没关系吧
效率的问题只是内存分配导致的.
S:=S+'a';估计会慢一点.
没有测试,只是猜想.
 
每个字符串向后偏移8字节,用一个Cardinal变量来表示它的引用计数,重新分配内存,必然有新的引用计数
 
var
S:string;
I:Cardinal;
begin
S:='';
for I:=1 to 1000000 do
S:=S+'a'
//每次都要分配s的内存空间,所以慢
end;

var
S:String;
I:Cardinal;
begin
SetLength(S,1000000);//只一次都要分配s的内存空间,所以快
for I:=1 to 1000000 do
S:='a';
end;
 
楼上的请先回答问题二:
用到的S[1]为读取操作,会不会改写引用计数?
 
成都]千余 13:19:46
第一个问题
S的引用计数为-1

[铁岭] 13:20:21
测试一下,的确是
[铁岭] 13:20:58
不过不是说常量字符串的引用计数才是-1吗?
不是指
const
S:String

[成都]千余 13:21:55
事实证明,你如果写在过程里的局部string
类型赋常量,它还是这么认为的
[合肥]飞刀 13:22:00

[铁岭] 13:22:36

[成都]千余 13:22:46
跳什么跳,有意见赶紧说哈
[合肥]飞刀 13:23:03
千余
[广州]藏镜人 13:23:04

[铁岭] 13:23:24
引用计数是不是指有多少个变量(指针)指向这个字符串?
[成都]千余 13:23:35
不信,你把它声明为全局的
[成都]千余 13:23:42

[成都]千余 13:24:08
关于引用计数这个概念
就是你要引用这段内存块

其余见另贴
 
接受答案了.
 
不会存在“引用计数被改写”的问题。对于任何一个非空字符串,它的引用计数永远为1。如果内存管理模块发现有试图改变引用计数的操作的话,会首先把字符串内容复制一遍--这就是Delphi帮助里面经常会提到的“为了确保引用计数为1的copy on write机制”。

对于某个字符串变量s,如果你想知道执行一项操作以后它是否被copy on write过,有一个很简单的判断方法:在执行该项操作的前后,分别用Pointer(s)取出字符串的地址,如果前后两个地址值不相等,那这个字符串就肯定就被copy on write过了--也就是你想知道的“引用计数是否被修改过了”。需要注意的是,取字符串地址的时候不能用PChar(s)或@s[1]操作来进行,因为这两种操作都可能引发copy on write机制,而Pointer(s)就不会。
 
后退
顶部