GetMem x ReallocMem

时间:2009-02-20 15:31:42

标签: delphi arrays memory-management

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

Delphi 2009对ReallocMem的帮助,与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;

begin
  ReallocMem(FItems, Value * SizeOf(Pointer));
  Dispose(FItems);
end;

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

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;

2 个答案:

答案 0 :(得分:20)

GetMem总是分配内存,FreeMem总是释放/释放内存,ReallocMem可以做一个,另一个,或两者兼而有之。事实上,如果使用得当,ReAllocMem实际上是唯一需要的内存管理API。如果你从一个nil指针开始,并调用大小>的ReAllocMem; 0,然后它就像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;

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

GetMem(Rec, SizeOf(Rec^));
Initialize(Rec);
...
Finalize(Rec);
FreeMem(Rec);

对于您给出的示例,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;

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

答案 1 :(得分:3)

GetMem分配一块内存。 ReallocMem重新分配一块内存。

但你最好使用动态数组:

var
  FItems : array of TMemberDataList;

begin
  SetLength(FItems, Value);
end;

它更像是德尔福的方式。

示例

你可以这样做:

type
  TMemberDataList = array[0..MaxClassMembers -1] of TMemberData;

var
  FItems: TMemberDataList;
begin
  // Don't need to allocate FItems
end;

或者:

type
  TMemberDataList = array of TMemberData;

var
  FItems: TMemberDataList;
begin
  SetLength(FItems, MaxClassMembers);
end;

类变量是指针。因此,您不必像我们使用TP那样使用显式指针。您仍然可以使用指针记录或对象,但没有理由这样做。