0
votes

I wanted to primarily ask whether using TList would be more appropriate than changing the length of a dynamic array each time a new item is to be appended. Like so:

SetLength(DynamicArray, Length(DynamicArray)+1);
DynamicArray[length(DynamicArray)] := NewElement; 

Assuming that it is more approrpiate.. I was wondering if something like this would work if I wanted to make a global dynamic array, accessible by all functions in the unit.

type
   Tdata = Record
     y: TList<real>;
     x: TList<integer>;
End;

var
  data: Tdata;

procedure TForm1.FormCreate(Sender: TObject);
begin
  data.y  := TList<real>.Create;
  data.y.add(1.2);
  data.y.add(2.3);
end;

procedure TForm1.ButtonClick(Sender: TObject); // Some button click event
begin
  Memo1.lines.add(data.y.count); // Should output 2
end;

I'm confused as to where I need to create the TList, and why we need to create it in the first place, unlike a normal array. Do I need to create the TList again in the event function, and when would I free it? I am following this example, but i'm still confused how this would work with functions? Thanks, Jonathon

1
Create it before you first use it. Destroy after you last use it.David Heffernan
FWIW, In Delphi use Double or Single. Real is a legacy type, and depending on settings, it can even be different. Real usually maps to Double but rather use that type directly, to be sure.Rudy Velthuis
Please specify your Delphi version.Uwe Raabe
Hi, i'm using Delphi 10.2.2Jonathon
Since Delphi XE7 you can add to a dynamic array with DynamicArray := DynamicArray + [NewElement]Brian

1 Answers

2
votes

I'm confused as to where I need to create the TList, and why we need to create it in the first place, unlike a normal array.

A TList is an object that must be instantiated by a call to Create. Like any object that is allocated on the heap, it must be created before use.

When you don't need it anymore, it must be deallocated by a call to Free. Note that a TList has other characteristics than an array. It has methods, properties, etc, to handle sorting, comparisons, insertion and things like that.


A "normal" array can be either a static array or a dynamic array.

  • A dynamic array is a managed type, where the lifetime is automatically handled by the use of a reference count. It is allocated to the heap by a call to SetLength, or by a concatenation with another array or value.
  • A static array is automatically stack allocated whenever it is within scope, and thus needs no explicit creation.

Do I need to create the TList again in the event function, and when would I free it?

In your example, the variable data is a global. Once the x or y fields have been allocated, they are alive until they are destroyed. So, no you don't have to create them again.

As @Remy says, if you want to use the data variable throughout the unit, it can be initialized and finalized in the initialization and finalization part of the unit.


I wanted to primarily ask whether using TList would be more appropriate than changing the length of a dynamic array each time a new item is to be appended.

Like mentioned above, a TList<T> is an object with methods for sorting etc. If you don't need those extra functions, a dynamic array is ok.

If you are thinking about performance, use a profiler first to find if you actually will gain anything by optimizing code. Adding items one by one on a dynamic array may be slower than using a TList. A TList will grow its internal array in larger chunks to avoid too much heap reallocations.