2

将本地动态数组的长度设置为零(不再需要时)是否具有内存使用优势?

例如:

var
  MyArray : array of string;
begin
  <filling my array with a lot of items....>

  <doing some stuffs with MyArray>

  //from here on, MyArray is no more needed, should I set its length to zero?
  SetLength(MyArray, 0);

  <doing other stuffs which doesn't need MyArray...>
end;
4

2 回答 2

6

在 Delphi 中,动态数组是引用计数的。

因此,如果你这样做

MyArray := nil;

或者

Finalize(MyArray);

或者

SetLength(MyArray, 0);

该变量MyArray将不再指向动态数组堆对象,因此其引用计数将减少 1。如果这使引用计数降至零,这意味着没有变量指向它,它将被释放。

示例 1

所以在

var
  a: array of Integer;
begin

  SetLength(a, 1024*1024);

  // ...

  SetLength(a, 0);

  // ...

end

你将释放内存SetLength(a, 0)假设a是唯一指向这个堆对象的变量

示例 2

var
  b: TArray<Integer>;

procedure Test;
var
  a: TArray<Integer>;
begin

  SetLength(a, 1024*1024);

  b := a;

  SetLength(a, 0);

  // ...

end

SetLength(a, 0)不会释放任何内存,因为b仍然是指原始数组。不过,它会将引用计数从 2 减少到 1。

示例 3

而且,当然,在

var
  a: array of Integer;
begin

  SetLength(a, 1024*1024);

  // ...

  SetLength(a, 0);

end

最后一次调用SetLength完全没有必要,因为局部变量a无论如何都会超出下一行代码的范围,这也减少了堆对象的引用计数。

于 2020-11-20T10:22:57.977 回答
2

是的,当您将动态数组的长度设置为零时,如果没有其他变量/对象正在引用内存,它正在使用的内存将被释放回可用的堆内存(不一定返回 Windows 内存,因此您可能看不到任务管理器中的好处,但是您的 Delphi 程序需要更长的时间才能从 Windows 分配额外的内存,因为它将首先使用可用的堆内存,您已将“MyArray”的大小添加到该堆内存中)。

于 2020-11-20T10:22:00.617 回答