How to append one array to another array of the same type without using iterative statements (for
or while
loops) in Delphi?
If you don't mind that your original array is destroyed, then there is a hackish solution. It is probably a lot faster than a loop, because each iteration of the loop must add one reference, while DestructiveConcatArrays
preserves the reference count.
This means that copies of the strings to be moved are not allowed. They are either in Destination
, or in Source
, but can't be in both at the same time. Otherwise their refcounts would have to be updated anyway -- in a loop.
Between the Move
and the FillChar
, all string references copied over are not properly refcounted. But after the FillChar
, they are again. Care must be taken that nothing, no thread, should be able to access the Source
array in that unstable state.
In other words: the following does not require the RTL to add or remove references, but it is tricky and it destroys the original (second) array:
procedure DestructiveConcatArrays(var Destination, Source: TArray);
var
LenD, LenS: Integer;
begin
LenD := Length(Destination);
if LenD = 0 then
Destination := Source
else
begin
LenS := Length(Source);
if Length(Source) > 0 then
begin
SetLength(Destination, LenD + LenS);
// Copy strings -- Afterwards, the refcounts of all strings copied over are
// out of sync.
Move(Source[0], Destination[LenD], LenS * SizeOf(string));
// Clear Source -- Afterwards, all refcounts are in sync again.
FillChar(Source[0], LenS * SizeOf(string), 0);
end;
end;
Source := nil;
end;
The above is not a general solution. It is a hack, designed for this single purpose only. But it works as expected. I tested that. But it is not thread-safe, although it can probably be made to be.
This is very much what C++ introduced with move semantics for rvalue expressions. Just consider the Source
as an rvalue.