【问题标题】:Delphi - Manage a TList with dynamic arrayDelphi - 使用动态数组管理 TList
【发布时间】:2020-08-08 05:36:51
【问题描述】:

我有一个用于绘制样条曲线的组件,它是 TPoint 数组中 Spline 过程的参数。 现在,我想创建 n 个 TPoint 的动态数组,将其保存在 TList 中,并在调用后绘制样条线。

附:德尔福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;

... 并且不工作。 :-(

【问题讨论】:

  • 你应该使用TList&lt;TArray&lt;TPoint&gt;&gt;而不是TList(使用Generics.Collections)。
  • 谢谢,现在可以了。

标签: delphi


【解决方案1】:

非通用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;

更好的解决方案是改用通用System.Generics.Collections.TList&lt;T&gt;,其中TTArray&lt;TPoint&gt;。然后将为您正确管理引用计数,例如:

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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多