GetMem x ReallocMem

Ces*_*ero 5 arrays delphi memory-management

System.GetMem和System.ReallocMem有什么区别?

ReallocMem的Delphi 2009帮助,与GetMem的描述完全相同.System.FreeMem和System.Dispose如何

我应该对数组使用什么?

type
  PMemberDataList = ^TMemberDataList;
  TMemberDataList = array[0..MaxClassMembers -1] of PMemberData;

var
  FItems: PMemberDataList;

begin
  GetMem(FItems, Value * SizeOf(Pointer));
  FreeMem(FItems);
end;
Run Code Online (Sandbox Code Playgroud)

要么

begin
  ReallocMem(FItems, Value * SizeOf(Pointer));
  Dispose(FItems);
end;
Run Code Online (Sandbox Code Playgroud)

在人们建议之后,我将FItems声明为记录类型,而不是指向记录的指针,将TMemberDataList声明为动态数组,将SetLength声明为(de)alloc数组,将New/Dispose声明为数据

type
  PMemberDataList = ^TMemberDataList;
  TMemberDataList = array of PMemberData;
var
  Items: TMemberDataList;
  Item: PMemberData;

// Add
begin
  Setlength(Items, 1);
  New(Item);
  Items[0]:= Item
end;

// Remove
begin
  Dispose(Items[0]);
  Setlength(Items, 0);
end;
Run Code Online (Sandbox Code Playgroud)

All*_*uer 20

GetMem总是分配内存,FreeMem总是释放/释放内存,ReallocMem可以做一个,另一个或两者兼而有之.事实上,如果使用得当,ReAllocMem实际上是唯一需要的内存管理API.如果以nil指针开头,并调用大小> 0的ReAllocMem,那么它就像GetMem一样.如果你调用大小= 0的ReAllocMem,那么它就像FreeMem一样.它实际上"重新分配"内存的唯一时间是指针是非零并且大小> 0.

New和Dispose用于处理类型指针或你的"old-skool"人,旧的Turbo Pascal对象模型(旧的"对象")语法.New和Dispose也将确保任何类型指针作为参考托管类型将正确初始化该类型.例如,给定以下内容:

type
  PMyRec = ^TMyRec;
  TMyRec = record
    Name: string;
    Value: Variant;
  end;

var
  Rec: PMyRec;
begin
  New(Rec);
  try
    Rec.Name := 'TestValue';
    Rec.Value := 100;
    ...
  finally
    Dispose(Rec);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

New和Dispose将确保正确初始化并最终确定或清理记录的Name和Value字段.在上述情况下,New和Dispose相当于:

GetMem(Rec, SizeOf(Rec^));
Initialize(Rec);
...
Finalize(Rec);
FreeMem(Rec);
Run Code Online (Sandbox Code Playgroud)

对于你给出的例子,Gamecat是对的,你可能最好使用动态数组,因为它们更好地由编译器管理,它们也有自己的内在长度.在您的示例中,您必须单独跟踪数组中的项目数,这样无论您在数组中传递什么,您还必须传递当前分配的长度.通过使用动态数组,所有信息都可以整齐地打包在一起.这将允许您通过简单地执行以下操作之一来迭代数组而不管当前长度:

var
  Member: TMemberData;
  Items: array of TMemberData;
  ...
begin
  SetLength(Items, Value);
  for Member in Items do  // iterate over each element in the array
  ...
  for Low(Items) to High(Items) do // same as above only using std functions
  ...
end;
Run Code Online (Sandbox Code Playgroud)

最后,您可能想要使用动态数组的另一个原因是,如果TMemberData包含字符串,变体,接口或其他"托管"类型,它们将被正确初始化并最终确定,而无需手动执行.

  • @Allen:你的答案应该加到Delphi帮助:) (5认同)