This is a new site that's currently running on alpha code. There are going to be bugs. If you discover any, please report them on the site's issues page (GitHub account required). Thanks.
Warning: Many URLs are going to change. Refer to the README file to discover which library project's documentation has been completed.
Project: Array Utilities Unit
Unit: DelphiDabbler.Lib.ArrayUtils
Record: TArrayUtils
Applies to: ~>0.1
class procedure PopAndFree<T: class>(var A: TArray<T>);
static;
Removes and frees the last element from a non-empty array of TObject descendants.
The length of the array is reduced by one.
Parameters:
A - Array from which the element is to be removed and freed. The array is updated in place when the element is deleted.
Array elements must be TObject descendants.
Preconditions:
If it is not necessary to free an object that is popped off an array then Pop<T> should be used instead of PopAndFree<T: class>.
There is no corresponding object version of Push<T> for use with PopAndFree<T: class>. This is not necessary since pushing an object requires no special handling. Just use Push<T> where T is set to the required class type.
This example illustrates how PopAndFree<class T> varies from Pop<T>.
The example uses custom class TObjectEx that records the number of objects currently instantiated.
type
TObjectEx = class
public
var ID: Char;
class var InstanceCount: Integer;
constructor Create(AID: Char);
destructor Destroy; override;
end;
{ TObjectEx }
constructor TObjectEx.Create(AID: Char);
begin
inherited Create;
ID := AID;
Inc(InstanceCount);
end;
destructor TObjectEx.Destroy;
begin
Dec(InstanceCount);
inherited;
end;
procedure PopAndFree_Eg;
var
A: TArray<TObjectEx>;
Obj, ShiftedObj: TObjectEx;
begin
// Start with no objects
Assert(TObjectEx.InstanceCount = 0, 'TObjectEx <> 0 instances');
// Create array of 3 objects using Push<T>
SetLength(A, 0);
TArrayUtils.Push<TObjectEx>(A, TObjectEx.Create('C'));
TArrayUtils.Push<TObjectEx>(A, TObjectEx.Create('B'));
TArrayUtils.Push<TObjectEx>(A, TObjectEx.Create('A'));
Assert(Length(A) = 3, 'Array length <> 3');
Assert(TObjectEx.InstanceCount = 3, 'TObjectEx <> 3 instances');
Assert(TArrayUtils.Last<TObjectEx>(A).ID = 'A', 'Last object ID <> A');
// Pop last object with PopAndFree<T:class>:
// this will remove it from the array and free it
TArrayUtils.PopAndFree<TObjectEx>(A);
// check object was removed from array
Assert(Length(A) = 2, 'Array length <> 2');
// check removed object was freed
Assert(TObjectEx.InstanceCount = 2, 'TObjectEx <> 2 instances');
Assert(TArrayUtils.Last<TObjectEx>(A).ID = 'B', 'Last object ID <> B');
// Pop new last object with Pop<T>:
// this will remove it from the array but not free it
ShiftedObj := TArrayUtils.Pop<TObjectEx>(A);
// check object removed from array
Assert(Length(A) = 1, 'Array length <> 1');
// check removed object was not freed
Assert(TObjectEx.InstanceCount = 2, 'TObjectEx <> 2 instances');
Assert(TArrayUtils.Last<TObjectEx>(A).ID = 'C', 'Last object ID <> C');
// Tidy up remaining un-freed objects
ShiftedObj.Free;
for Obj in A do
Obj.Free;
Assert(TObjectEx.InstanceCount = 0, 'TObjectEx <> 0 instances');
end;