arrays - 增加指针数组的通用函数

标签 arrays delphi pointers

我正在编写具有如下数据结构的代码:

type
  TData1 = record
    IntField: Integer;
    StrField: string;
  end;

  TData2 = record
    DateField: TDateTime;
    StrField: string;
  end;

var
  AData1 = array of ^TData1;
  AData2 = array of ^TData2;

有时我必须向其中一个数组添加一个元素,如下所示:

L := Length(AData1);
SetLength(AData1, L + 1);
New(AData1[L]);

如何编写一个过程来增加数组大小并为适用于任何类型指针的新项目分配内存?并且必须在不更改记录(TData1,TData2)和数组(AData1,AData2)的定义的情况下完成,因此不会破坏现有代码。

Ps:我对指针和此类编程没有太多背景,我当然会使用对象和动态链接列表,但在这种情况下,它是遗留代码,我无法更改它,至少对于现在。

最佳答案

更新:

这不是完整的答案。使用 David 提到的 TDynArray 可能会解决您的问题。

使用 RTTI,我为您提供了另一个解决方案。它是一个通用解决方案,您可以轻松添加更多功能/功能。它将保留您的类型声明。包括添加/删除记录的示例。

记录TDynPtArray处理任何指向记录的动态指针数组。它通过 Init 调用进行初始化:

DPA.Init(TypeInfo(TData1), AData1);
Data1 := DPA.Add;  // Adds a record with default values and
                   // returns a pointer to the record
DPA.Remove; // Finalizes/deallocates the last record and 
            // shrinks the dynamic array

-

uses
  Windows,System.SysUtils,System.TypInfo;

Type
  TPtArray = array of Pointer;
  PPtArray = ^TPtArray;
  TDynPtArray = record
  private
    FDynArray: PPtArray;
    FTypeInfo: PTypeInfo;
    FTypeData: PTypeData;
  public
    constructor Init( T: Pointer; var dynArray);
    function Add : Pointer;
    procedure Remove;
    procedure Clear;
  end;

constructor TDynPtArray.Init(T: Pointer; var dynArray);
begin
  FTypeInfo := T;
  if  (FTypeInfo^.Kind <> tkRecord) then
    raise Exception.CreateFmt('%s is not a record',[FTypeInfo^.Name]);
  FTypeData := GetTypeData( FTypeInfo);
  FDynArray := @dynArray;
end;

function TDynPtArray.Add: Pointer;
var
  L: integer;
begin
  L := Length(FDynArray^);
  SetLength(FDynArray^,L+1);
  GetMem( FDynArray^[L], FTypeData^.elSize);
  ZeroMemory( FDynArray^[L], FTypeData^.elSize);
  Result := FDynArray^[L];
end;

procedure RecordClear(var Dest; TypeInfo: pointer);
asm
{$ifdef CPUX64}
  .NOFRAME
{$endif}
  jmp System.@FinalizeRecord
end;

procedure TDynPtArray.Remove;
var
 L: integer;
begin
  L := Length(FDynArray^);
  if (L = 0) then
    exit;
  RecordClear( FDynArray^[L-1]^,FTypeInfo); // Finalize record
  FreeMem( FDynArray^[L-1], FTypeData^.elSize);
  SetLength(FDynArray^,L-1);
end;

procedure TDynPtArray.Clear;
begin
  while (Length(FDynArray^) <> 0) do
    Self.Remove;
end;

还有一个小测试:

type
  PData1 = ^TData1;
  TData1 = record
    IntField: Integer;
    StrField: string;
  end;
  TData1Arr = array of PData1;

var
  AData1: TData1Arr;
  Data1: PData1;
  DPA: TDynPtArray;
begin
  DPA.Init(TypeInfo(TData1), AData1);
  Data1:= DPA.Add;
  Data1^.StrField := '111';
  WriteLn(Data1^.IntField);
  WriteLn(Data1^.StrField);

  DPA.Clear;

  ReadLn;
end.

关于arrays - 增加指针数组的通用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11795338/

相关文章:

arrays - Fortran 算法如何使用这些数组?

python - 用 Python 发牌?

Delphi 中的 Javascript 和 youtube api

c - 我如何编写一个函数来复制一个项目数组,用于复制一些定义数量的项目

c - 数组作为 scanf 函数参数。地址运算符

c - 你如何在 C 中创建一个结构数组?

php - PHP current() 函数是否返回数组的副本或引用?

delphi - 错误 : Constant or type identifier expected

delphi - 如何在TWebBrowser中设置语言

C:帮助理解指针