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.2 - Jonathon
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.