Delphi字符串和引用计数

时间:2010-02-13 06:08:39

标签: delphi string reference memory-management

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;

3 个答案:

答案 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)

是的,字符串被引用计数,仅当通过变量修改内容时才创建副本(写入语义上的副本),更多信息在这里:

http://www.codexterity.com/delphistrings.htm