Delphi使用带字符串的引用计数。
这是否意味着'1234567890'只有一个内存分配 和所有a,b,c,d,e和f.s参考吗?
type
TFoo = class
s: string;
end;
const
a = '1234567890';
b = a;
c : string = a;
var
d: string;
e: string;
f: TFoo;
function GetStr1(const s: string): string;
begin
Result := s;
end;
function GetStr2(s: string): string;
begin
Result := s;
end;
begin
d := GetStr1(b);
e := GetStr2(c);
f := TFoo.Create;
f.s := a;
end;
答案 0 :(得分:10)
是的,您的具体示例中只有一个分配。如果您使用了UniqueString
,如mghie所说,或者您是否动态构建了字符串,那么即使字符串内容与其他字符串相同,您也会得到新的字符串分配。
然而,关于您的具体示例的一个有趣的事实:实际上没有为字符串'1234567890'“分配”内存。字符串常量的数据存储在磁盘上的可执行映像中,并在代码访问时由OS分页。它占用内存地址空间,作为整个可执行模块的内存映射的一部分,但由于它由磁盘上的原始可执行文件支持,因此它不构成进程提交的内存的一部分,并且不需要支持页面文件。
例如,此程序将在运行时报告访问冲突:
{$apptype console}
uses SysUtils;
const
s = '1234567890';
procedure Change(const r: string);
var
p: PChar;
begin
p := PChar(r);
p^ := 'x';
end;
begin
try
Change(s);
except
on e: Exception do
Writeln(e.Message);
end;
end.
答案 1 :(得分:6)
answer by jxac的小额添加:
当代码中调用UniqueString()
时,[]
访问字符串中的字符时,以及字符串被强制转换为PChar
时,也会创建副本。即使只能读取PChar
和字符串元素,也会发生这种情况。
知道如何从可能共享的字符串强制使用唯一字符串非常重要,因为必须使用只读字符串指针调用Windows API函数,PChar
到字符串常量是{ 。在这种情况下,需要首先将常量复制到变量,因此强制转换将返回指向可写内存的PChar
。
答案 2 :(得分:5)
是的,字符串被引用计数,仅当通过变量修改内容时才创建副本(写入语义上的副本),更多信息在这里: