3

在 pascal 中,我敢于清理数组的唯一方法是简单地遍历它并清除它,但效率极低。我不能通过为其分配一个空数组来简单地重新初始化它吗?

program arrays;
  var
    working, empty : array [1..10] of integer;
begin
  working[3] := 5;
  working:= empty;
end.

这样做可以吗,这会适得其反吗?

4

3 回答 3

8

如果要清除数组,请编写:

working:= empty;

实际上会通过将数组内容复制到...来进行清除,在您情况下是无效的,因为它是一个全局变量,因此用 0 初始化。emptyworkingempty

恕我直言,定义此类全局变量不是一个好习惯。全局变量在大多数情况下都是邪恶的(除非您知道自己在做什么),并且在声明它们用 0 初始化的情况下是没有意义的。

实际上,如果empty是在栈上初始化的(即var方法内的a),此时就填充了栈上的任何东西,即一些随机数据。

如果您想快速初始化一个不包含任何引用计数类型(如string)的数组,您可以编写:

fillchar(working,sizeof(working),0);

如果您的数组包含托管类型,您可以编写:

finalize(workingWithStringInside); // to safely release internal managed types
fillchar(workingWithStringInside,sizeof(workingWithStringInside),0);

这是可能的更快的代码(比变量副本更快),并且听起来是一个更好的选择。

于 2013-08-07T16:53:34.387 回答
5

这绝对没问题。代码的语义正是您所需要的。当然,Delphi 编译器会发出代码来执行简单而高效的内存复制。编译器能够做到这一点,因为您有一个固定长度的数组,其元素是简单的值类型。如果 FPC 没有产生非常相似的代码,我会感到惊讶。

即使您的数组包含托管类型(它不包含),赋值运算符也会生成尊重这些托管类型的代码。

作为最后的评论,充满零的数组应该是一个常数。

于 2013-08-07T15:46:18.133 回答
0

一种简单的方法是不要在类型中设置变量的长度...并使用 SetLength 为您初始化数组...来自 Delphi 帮助:当 S 是必须初始化的类型的动态数组时,新分配的空间设置为 0 或 nil。

type
  TIntArray =  Array of Integer;

procedure WorkArrays(var aWorking: array of integer);
begin
  if High(aWorking) >= 0 then
    aWorking[0] := 1;
  if High(aWorking) >= 3 then
    aWorking[3] := 5;
end;

procedure WorkArrays2(var aWorking: array of integer);
begin
  if High(aWorking) >= 1 then
    aWorking[1] := 4;
  if High(aWorking) >= 9 then
    aWorking[9] := 7;
end;

procedure WorkArrays3(var aWorking: TIntArray);
begin
  SetLength(aWorking, 0);
  SetLength(aWorking, 4);
  aWorking[0] := 1;
  aWorking[3] := 5;
end;

procedure WorkArrays4(var aWorking: TIntArray);
begin
  SetLength(aWorking, 0);
  SetLength(aWorking, 10);
  aWorking[1] := 4;
  aWorking[9] := 7;
end;

procedure TForm58.ShowArrays(aWorking: array of integer);
var
  a_Index: integer;
begin
  for a_Index := Low(aWorking) to High(aWorking) do
    Memo1.Lines.Add(IntToStr(aWorking[a_Index]));
end;

procedure TForm58.ShowArrays2(aWorking: TIntArray);
var
  a_Index: integer;
begin
  for a_Index := Low(aWorking) to High(aWorking) do
    Memo1.Lines.Add(IntToStr(aWorking[a_Index]));
end;

procedure TForm58.Button1Click(Sender: TObject);
var
  a_MyArray: array of integer;
  a_MyArray1: TIntArray;
begin
  //SetLength(aWorking, 0);
  SetLength(a_MyArray, 3);//note this is a Zero based Array...0 to 2
  WorkArrays(a_MyArray);//note aWorking[3] will not show...because High is 2...
  ShowArrays(a_MyArray);
  SetLength(aWorking, 0);
  SetLength(a_MyArray, 10);//note this is a Zero based Array...0 to 9
  WorkArrays2(a_MyArray);
  ShowArrays(a_MyArray);
  WorkArrays3(a_MyArray1);
  ShowArrays2(a_MyArray1);
  WorkArrays4(a_MyArray1);
  ShowArrays2(a_MyArray1);
end;
于 2013-08-08T16:04:47.497 回答