I have a couple of questions and confusions around initialization and I appreciate any help for clarifying them.
Question1:I always faced this one, but never find out why.
Considering these two Tests:
Test1:
program Project1;
var
A: array[0..10] of integer;
I: integer;
begin
for I := 0 to High(A) do
WriteLn(A[I]);
ReadLn;
end.
Test2:
program Project1;
procedure Test;
var
A: array[0..10] of integer;
I: integer;
begin
for I := 0 to High(A) do
WriteLn(A[I]);
end;
begin
Test;
ReadLn;
Why in Test1, (as far as I know), A is zeroed, but not in Test2?
In both cases FPC warns about not initialized value.
Question2:Why Initialize(A); does not zero the array?
procedure Test;
var
A: array[0..10] of integer;
I: integer;
begin
Initialize(A);
for I := 0 to High(A) do
WriteLn(A[I]);
end;
For example if I use Initialize on a record, it will zero any value in it, but not for arrays. And it is documented as "Initializing means zeroing out the memory area".
What is the logic behind this?
I guess, one can say, it does Initialize the memory of array, but not the induvial items, but the array in it self is a type, so why not Initializing (zeroing out) it too?
Question3:And to add to confusion of myself, Initialize is documented as "In this sense it is close in functionality to Default, but Default requires an already initialized variable."
But if I try to do this, I will get a zeroed array, so they are not the same.
procedure Test;
type
TA = array[0..10] of integer;
var
A: TA;
I: integer;
begin
A := Default(TA);
for I := 0 to High(A) do
WriteLn(A[I]);
end;
Question4:As said in documentation, "Default requires an already initialized variable." What does it mean? Is it best practice to call Initialize first and then Default?
Considering this sample:
program Project1;
{$mode delphi}
type
{ TTest }
TTest = record
I: integer;
class operator Initialize(var AValue: TTest);
class operator Finalize(var AValue: TTest);
class operator AddRef(var AValue: TTest);
class operator Copy(constref A: TTest; var B: TTest);
end;
class operator TTest.Initialize(var AValue: TTest);
begin
WriteLn('Initialize: ', QWord(@AValue));
end;
class operator TTest.Finalize(var AValue: TTest);
begin
WriteLn('Finalize: ', QWord(@AValue));
end;
class operator TTest.AddRef(var AValue: TTest);
begin
WriteLn('AddRef: ', QWord(@AValue));
end;
class operator TTest.Copy(constref A: TTest; var B: TTest);
begin
WriteLn('Copy: ', QWord(@A), ' : ', QWord(@B));
end;
procedure Test1;
var
V: TTest;
begin
end;
procedure Test2;
var
V: TTest;
begin
Initialize(V);
end;
procedure Test3;
var
V: TTest;
begin
V := Default(TTest);
end;
begin
WriteLn('Test1');
Test1; //No Initialize
WriteLn('Test2');
Test2; //Two Initialize on same pointer!
WriteLn('Test3');
Test3; //One Initialize
ReadLn;
//Log:
//Test1
//Test2
//Initialize: 20971068
//Initialize: 20971068
//Finalize: 20971068
//Test3
//Initialize: 20971068
//Copy: 20971064 : 20971068
//Finalize: 20971068
end.
Question5:Why Test2 is initialize V two times for the same pointer?
Question6:At Test3, Pointer 20971068 is initialized, but not 20971064. But FPC copies 20971064 to 20971068. Why? and how should I manage it to not duplicated a cost of copy? I thought Default, makes the value default, but it seem it makes a initialized(!) value and copy it to the variant.
Documentation of initialize:
https://www.freepascal.org/docs-html/rtl/system/initialize.htmlFor future readers:
https://forum.lazarus.freepascal.org/index.php/topic,62706.msg474502.html#msg474502