On Emba's website, it is stated that an OUT parameter (does not say which type, so I assume it applies to all types) should not be used for input because its value is "discarded".
By discarded, I interpret (even though we are not at the Bible Study hour) that the value is zeroed.
With an out parameter, however, the initial value of the referenced variable is discarded by the routine it is passed to.
But this simple code shows that "i" is not discarded (in none of the cases)!
Procedure TestInteger(OUT i: Integer);
Begin
if i = 7
then i:= 14;
End;
TYPE TMyRec = record
i: Integer;
end;
Procedure TestRec(OUT R: TMyRec);
Begin
End;
procedure TfrmTest.btnTestClick(Sender: TObject);
begin
VAR i: Integer:= 7;
TestInteger(i);
VAR MyRecord: TMyRec;
MyRecord.i:= 7;
TestRec(MyRecord);
Caption:= IntToStr(MyRecord.i);
end;
So, is the documentation wrong? Is my "interpretation" wrong, or is the compiler wrong?
CodePudding user response:
Decorating a parameter with out
means that the parameter will only be used to return a value to the caller; the routine must not make any assumption about the initial value of the parameter.
The out
decoration serves as a semantic hint to the programmer. In addition, the compiler may use the knowledge that the "passed" value will not be used to optimize the generated code.
However, there is no guarantee whatsoever that a "passed" value is indeed cleared. After all, such a guarantee would serve no purpose; on the contrary, it would likely force the compiler to generate slightly less efficient code (because zeroing memory takes time).
Think of a watch manufacturer that makes watches able to function properly down to −50°C. You then make an order for a watch that only needs to be able to function properly down to −20°C. The manufacturer may use this knowledge to produce the watch more cheaply. However, there is absolutely no guarantee that the watch you are delivered will malfunction at −50°C, nor would you typically need such a guarantee. (But of course you must not use the watch below −20°C.)
With an out parameter, however, the initial value of the referenced variable is discarded by the routine it is passed to.
Well, since the programmer never uses the value, it is effectively "discarded", isn't it?
A bit later down on the same page:
The call to GetInfo immediately frees the memory used by MyRecord, before program control passes to the procedure.
Okay, this is hard not to consider as erroneous.
CodePudding user response:
Note that if you use a managed record it does call initialize and a 0 ends up in the caption.
TYPE TMyRec = record
i: Integer ;
class operator Initialize (out Dest: TMyRec);
end;
class operator TMyRec.Initialize (out Dest: TMyRec);
begin
dest.i := 0;
end;
This is more of a comment but code doesn't format well in comments.