На веб-сайте Emba указано, что параметр OUT (не указано, какой тип, поэтому я предполагаю, что он применим ко всем типам) не должен использоваться для ввода, поскольку его значение «отбрасывается».
Под словом «отброшено» я понимаю (хотя мы и не на уроке изучения Библии), что значение обнуляется.
Однако с параметром out начальное значение переменная отбрасывается подпрограммой, которой она передается.
Но этот простой код показывает, что значение, хранящееся в «i», не отбрасывается, а в «s»:
TYPE TMyRec = record
i: Integer;
end;
Procedure TestInteger(OUT i: Integer);
Begin
End;
Procedure TestRec(OUT R: TMyRec);
Begin
End;
Procedure TestStr(OUT S: string);
Begin
End;
procedure TfrmTest.btnTestRecClick(Sender: TObject);
begin
VAR MyRecord: TMyRec;
MyRecord.i:= 7;
TestRec(MyRecord);
Memo.Lines.Add('Test rec: '+ IntToStr(MyRecord.i));
end;
procedure TfrmTest.btnTestStrClick(Sender: TObject);
begin
VAR s: string:= 'x';
TestStr(s);
Memo.Lines.Add('Test str: '+ s);
end;
procedure TfrmTest.btnTestIntClick(Sender: TObject);
begin
VAR i: Integer:= 7;
TestInteger(i);
Memo.Lines.Add('Test int: '+ IntToStr(i));
end;
Итак, документация неверна? Просто формулировка неверна? Может быть, они имели в виду «проигнорировать», а не «отбросить»?
Отброшено не то же самое, что очищено. Вы можете найти дополнительную информацию о поведении наших параметров на delphisorcery.blogspot.com/2021/04/… и dalijap.blogspot.com/2021/03/…
@DalijaPrasnikar - Прямо в этом разделе они ясно говорят, что очищают память. Не так ли? "Вызов GetInfo сразу освобождает память"
Если вы поместите слово «отброшено» в строку между «проигнорировано» и «очищено», я думаю, что слово «отброшено» почти коснется «очищено».
@ServerOverflow: бесплатно <> заполнить нулями. Если у вас есть type TX = class A: Integer; end; var X: TX; begin X := TX.Create; try X.A := 394; finally X.Free; end;
, то вы явно «свободны» X
, но, скорее всего, X.A
будет 394
некоторое время, пока память не будет перезаписана чем-то другим (что может быть в любой момент — вы НЕ ДОЛЖНЫ использовать (старый объект указывает на by) X
после освобождения).
Я ответил на то, что вы тут процитировали. остальное я не читал. Сказанное там не совсем верно в том смысле, что верно не для всех типов. Обнуление допустимо только для управляемых типов, которые необходимо инициализировать нулем, иначе они будут нарушены. и это только потому, что этого требует сторона С++.
Я думаю, что они хотели сказать "не учитываются" вместо "отбрасываются".
Украшение параметра out
означает, что параметр будет использоваться только для возврата значения вызывающей стороне; подпрограмма не должна делать никаких предположений о начальном значении параметра.
Украшение out
служит смысловой подсказкой программисту. Кроме того, компилятор может использовать информацию о том, что «переданное» значение не будет использоваться для оптимизации сгенерированного кода.
Однако нет никакой гарантии, что «переданное» значение действительно будет очищено. В конце концов, такая гарантия бесполезна; напротив, это, скорее всего, заставит компилятор генерировать немного менее эффективный код (поскольку обнуление памяти требует времени).
Подумайте о производителе часов, который делает часы, способные нормально функционировать при температуре до -50°C. Затем вы делаете заказ на часы, которые должны нормально функционировать только при температуре до -20°C. Производитель может использовать эти знания для удешевления производства часов. Тем не менее, нет абсолютно никакой гарантии, что часы, которые вам доставят, сломаются при температуре -50°C, и вам, как правило, такая гарантия не требуется. (Но, конечно, вы не должны использовать часы при температуре ниже -20°C.)
Однако с параметром out начальное значение переменной, на которую ссылаются, отбрасывается подпрограммой, которой оно передается.
Ну, поскольку программист никогда не использует это значение, оно эффективно «отбрасывается», не так ли?
Чуть позже на той же странице:
Вызов GetInfo немедленно освобождает память, используемую MyRecord, прежде чем управление программой перейдет к процедуре.
Ладно, это трудно не считать ошибочным.
"Ладно, это трудно не считать ошибочным" - Верно! Эмба четко говорит, что запись очищена (но это не так). Я распространил эту ошибочную информацию на все типы, переданные как Out.
@ServerOverflow: На самом деле «очистить» <> «бесплатно». Обычно, когда что-то «освобождается», память некоторое время остается неповрежденной, прежде чем она будет перезаписана, что может стать в любое время. Он не заполняется нулями. Все-таки я не понимаю, что Эмба вообще имеет в виду под "бесплатным" здесь
Возможно, они использовали free, чтобы подчеркнуть, что вы не можете передавать какое-либо входное значение через параметр out. Кажется, это просто неудачный выбор слов.
«поскольку программист никогда не использует это значение, оно эффективно отбрасывается» — лично я бы использовал более подходящее слово, например, «игнорировать».
Обратите внимание, что если вы используете управляемую запись, она вызывает инициализацию, и в заголовке заканчивается 0.
TYPE TMyRec = record
i: Integer ;
class operator Initialize (out Dest: TMyRec);
end;
class operator TMyRec.Initialize (out Dest: TMyRec);
begin
dest.i := 0;
end;
Это скорее комментарий, но код плохо форматируется в комментариях.
Простые типы имеют случайное значение при выделении памяти. В зависимости от того, как использовалась выделенная память, вы получаете интересные значения. Однако в вашем примере память, на которую сопоставляется значение, инициализируется значением 7. Здесь документация является скорее руководством, чем законом.