Welcome to the new DelphiDabbler Code Library Documentation.

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.

PopAndFree<T: class> class method

Project: Array Utilities Unit

Unit: DelphiDabbler.Lib.ArrayUtils

Record: TArrayUtils

Applies to: ~>0.1

class procedure PopAndFree<T: class>(var A: TArray<T>);
  static;

Description

Removes and frees the last element from a non-empty array of TObject descendants.

The length of the array is reduced by one.

Parameters:

Preconditions:

Note

  1. 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>.

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

Example

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;

See Also