2009-02-20 11 views
5

System.GetMem和System.ReallocMem有什么区别?GetMem x 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; 

SOLUTION

人意见后,我宣布FItems为记录类型,而不是指针记录,TMemberDataList动态数组,SetLength来(德)分配数组,新建/处理数据

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; 
+0

根据您更新的使用情况,它看起来像数组“拥有”成员数据。您可以通过使其成为TMemberData而不是PMemberData的数组来简化代码,而不是指向成员数据记录。 – 2009-02-23 19:06:06

回答

20

GetMem总是分配内存,FreeMem总是释放/释放内存,ReallocMem可以做一个,另一个或两者。事实上,如果使用得当,ReAllocMem实际上是唯一需要的内存管理API。如果你从一个零指针开始,调用大小大于0的ReAllocMem,那么它就像GetMem一样。如果您调用大小为0的ReAllocMem,则它的行为与FreeMem类似。它实际上“重新分配”内存的唯一时间是如果指针是非零和大小大于0.

新和Dispose被设计用于键入指针或为你“老skool”的人, 。年长的Turbo Pascal对象模型(老“对象)语法新的和处置也将确保任何类型的指针是一个管理型的引用可以正确地初始化该类型例如给出如下:

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将确保记录的名称和值字段被正确初始化并完成或清除。在上述情况下,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包含字符串,变种,接口或其他“管理”类型,它们将被正确初始化并最终完成,而无需手动完成。

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一样。您仍然可以使用指向记录或对象的指针,但没有理由这样做。

+0

@Gamecat:对于这种情况,我需要PMemberDataList作为var,作为方法参数传递。代码: SetLength(FItems^[I]^.ClassItems ^,Size); 引发异常 [DCC错误] JazzIntr​​ospector.pas(433):E2008不兼容的类型 – 2009-02-20 15:46:21

+0

不知道如何定义FItems,但不应该需要这些显式指针。 (我添加一个例子) – 2009-02-20 15:52:23