我正在编写具有如下数据结构的代码:
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/