delphi - Delphi - 使用动态数组管理 TList
问题描述
我有一个用于绘制样条曲线的组件,它是 TPoint 数组中样条曲线过程的参数。现在,我想创建 n 个 TPoint 的动态数组,将其保存在 TList 中,并在调用后绘制样条曲线。
PS德尔福XE5
例子:
var
l: TList;
procedure CreateSpline;
var i, x: byte;
p: TPoint;
a: array of TPoint;
begin
l := TList.Create;
for x := 0 to 9 do // create 10 splines
begin
SetLength(a, Random(10) + 5); Each spline has 5<n<15 points
for i := 0 to High(a) do
begin
p.X := Random(200) - 100; // X coord
p.Y := Random(200) - 100; // Y coord
a[i] := p; // add point to array
end;
l.Add(a); // add array to TList
end;
end;
procedure DrawSpline;
var i: byte;
a: array of TPoint;
begin
for i := 0 to 9 do
begin
a := l[i];
xyPlot.Spline(a); // Draw the spline (xyPlot is the graphic component)
end;
end;
...并且不工作。:-(
解决方案
非泛型System.Classes.TList
只是一个原始指针的容器,它不知道它持有什么。动态数组是引用计数的,TList
不会为您管理引用计数,因此您必须手动执行以确保当数组在列表中时引用计数增加,例如:
ar
l: TList;
procedure CreateSpline;
var
i, x: byte;
p: TPoint;
a: TArray<TPoint>;
aptr: Pointer;
begin
l := TList.Create;
for x := 0 to 9 do // create 10 splines
begin
SetLength(a, Random(10) + 5); // Each spline has 5<n<15 points
for i := 0 to High(a) do
begin
p.X := Random(200) - 100; // X coord
p.Y := Random(200) - 100; // Y coord
a[i] := p; // add point to array
end;
TArray<TPoint>(aptr) := a;
try
l.Add(aptr); // add array to TList
except
TArray<TPoint>(aptr) := nil;
raise;
end;
a := nil;
end;
end;
{ alternatively:
procedure CreateSpline;
var
i, x: byte;
p: TPoint;
a: TArray<TPoint>;
begin
l := TList.Create;
for x := 0 to 9 do // create 10 splines
begin
SetLength(a, Random(10) + 5); // Each spline has 5<n<15 points
for i := 0 to High(a) do
begin
p.X := Random(200) - 100; // X coord
p.Y := Random(200) - 100; // Y coord
a[i] := p; // add point to array
end;
l.Add(Pointer(a)); // add array to TList
Pointer(a) := nil;
end;
end;
}
procedure DrawSpline;
var
i: byte;
a: TArray<TPoint>;
begin
for i := 0 to 9 do
begin
a := TArray<TPoint>(l[i]);
xyPlot.Spline(a); // Draw the spline (xyPlot is the graphic component)
end;
end;
...
// later, you need to decrement the refcounts before freeing/clearing the TList...
var
i: byte;
aptr: Pointer;
begin
for i := 0 to 9 do
begin
aptr := l[i];
TArray<TPoint>(aptr) = nil;
end;
l.Free;
end;
更好的解决方案是使用 GenericSystem.Generics.Collections.TList<T>
代替,其中T
is TArray<TPoint>
. 然后将为您正确管理引用计数,例如:
ar
l: TList<TArray<TPoint>>;
procedure CreateSpline;
var
i, x: byte;
p: TPoint;
a: TArray<TPoint>;
begin
l := TList<TArray<TPoint>>.Create;
for x := 0 to 9 do // create 10 splines
begin
SetLength(a, Random(10) + 5); // Each spline has 5<n<15 points
for i := 0 to High(a) do
begin
p.X := Random(200) - 100; // X coord
p.Y := Random(200) - 100; // Y coord
a[i] := p; // add point to array
end;
l.Add(a); // add array to TList
end;
end;
procedure DrawSpline;
var
i: byte;
a: TArray<TPoint>;
begin
for i := 0 to 9 do
begin
a := l[i];
xyPlot.Spline(a); // Draw the spline (xyPlot is the graphic component)
end;
end;
...
l.Free;
推荐阅读
- amazon-s3 - AWS S3 存储桶加密 - 存储桶属性设置与存储桶策略设置
- android - FirebaseAuth.DefaultInstance 后应用程序崩溃
- ffmpeg - ffmpeg 4.0.2 在网络关闭时不会停止
- virtual-machine - 在虚拟化环境中运行 RPA UI 交互
- internet-explorer-11 - 创建工作的基本示例聚合物 3 ie11
- dart - Stack inside Stack in flutter
- java - 将 concat 与 int 一起使用?(爪哇)
- python - python xarray刻度标签大小问题
- docker - 如何配置 docker 日志记录以有条件地发送到 CloudWatch?
- tfs - 成功构建后自动在 TFS 中合并已批准的 PR