Result
in Test is NOT always initially ()
I have found Do I need to setLength a dynamic array on initialization?, however I do not fully understand that answer
More importantly, what is the best approach to "break" the Result/A connection (I need the loop)? Perhaps some way to force the compiler to "properly" initialize? Manually adding Result := nil
as first line in Test?
function Test(var A: TArray<Integer>): TArray<Integer>;
begin
SetLength(Result, 3); // Breakpoint here
Result[0] := 2;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
A: TArray<Integer>; // Does not help whether A is local or global
I: Integer;
begin
for I := 1 to 3 do
A := Test(A); // At Test breakpoint:
// * FIRST loop: Result is ()
// * NEXT loops: Result is (2, 0, 0)
// modifying Result changes A (immediately)
A := Test(A); // Result is again ()
end;
While I hesitate to call this For
compiler optimization a bug, this is certainly unhelpful if modifying array elements directly:
function Test(var A: TArray<Integer>): TArray<Integer>;
begin
if Length(Result) > 0 then // Breakpoint
Result[1] := 66; // A modified!
SetLength(Result, 3);
Result[0] := Result[0] + 1; // A not modified
Exit;
A[9] := 666; // Force linker not to eliminate A
end;
After investigation, I conclude that functions that affect the entire array (e.g. SetLength
, Copy
or some other function that returns TArray<Integer>
) will -- unsurprisingly -- "break" the Result/A identicality created by the For
loop.
It would appear that the safest approach is (as per the answer linked to in the original post) to Result := nil;
as first line in Test.
If there are no further suggestions, I will eventually accept this as the answer.
NOTE:
As an added bonus, starting with Result := nil
prevents the array from being copied by SetLength
-- obvious, but for e.g. an array of 100000 being looped 100000 times this little modification effectuates a ~40% faster execution time