-
> Тимохов Дима © (02.06.17 14:15) [19]
интересно другое, FillChar зачем?
-
> Sha © (02.06.17 14:30) [20] > > Тимохов Дима © (02.06.17 14:15) [19] > интересно другое, FillChar зачем?
ибо
-
> Тимохов Дима © (02.06.17 14:37) [21]
так лучше не делать, ибо потенциально это может привести к затиранию нулем указателя на строку и, как следствие, к утечке памяти
-
> Sha © (02.06.17 14:41) [22] > > Тимохов Дима © (02.06.17 14:37) [21] > так лучше не делать, > ибо потенциально это может привести к затиранию нулем указателя > на строку и, как следствие, к утечке памяти
Конечно, ты прав. Вопрос, в другом, что код то в общем-то невинный. Зачастую что-то похожее может прийти еще из старого кода, а строка была добавлена позднее. И вот тебе и утечка. К тому же Button1 приводит к ошибке, Button2 - нет. Опять же, понятно почему. Я к тому, что может быть полезно для новичков знать такую особенность. Если уж очень мне надо сохранить функционал FillChar (т.е. умолчательную инициализацию), но не получить мемлик, то пишу обычно так: function InitPerson(const FIO: String; Age: Integer): TPerson;
var
R: TPerson;
begin
FillChar(R, SizeOf(R), 0);
R.FIO := FIO;
R.Age := Age;
Result := R;
end;
-
> Тимохов Дима © (02.06.17 14:48) [23] > Если уж очень мне надо сохранить функционал FillChar
а тут тоже FillChar не нужен, т.к. благодаря магии компилятора R будет проинициализирована
-
> Sha © (02.06.17 16:12) [24] > > Тимохов Дима © (02.06.17 14:48) [23] > > Если уж очень мне надо сохранить функционал FillChar > > а тут тоже FillChar не нужен, > т.к. благодаря магии компилятора R будет проинициализирована
и даже Integer? )))
-
а нафига его инициализировать, если это никогда не приведет к ошибке?
-
> Sha © (02.06.17 16:29) [26] > а нафига его инициализировать, если это никогда не приведет > к ошибке?
Предпочитаю не оставлять неинициализированные переменные.
-
FillChar не нужен более чем совсем, во-первых, он не делает ничего полезного, во-вторых затрудняет понимание кода.
В свое время бывший коллега (ныне покойный) писал такой код:
A := 0; A := FieldByName('B').AsInteger;
Когда его спросили, зачем первое присваивание, ответ был: "А вдруг поле не найдется"
-
> Игорь Шевченко © (03.06.17 10:35) [28] > FillChar не нужен более чем совсем, во-первых, он не делает > ничего полезного, во-вторых затрудняет понимание кода.
Иногда - нужен, иногда - не нужен. Зависит от ситуации.
В VCL пример есть. Вот, например DBTables.pas -> TDatabase.Execute, или StdCtrls.pas -> TCustomListBox.ItemRect. Факт - есть примеры использования FillChar для очистки результата типа record.
Еще раз: FillChar(Result,...) - это способ дать умолчательное значение для результата типа Record. Но этот способ таит в себе тонкости, которые надо знать начинающим программистам, которые еще не сталкивались с подобными тонкостями. Собственно, я для этого и написал свой комментарий выше.
-
Вообще-то FillChar как раз и нужен Если его не сделать то в первом коде в первом рекорде будет инвалидный указатель.
-
> Когда его спросили, зачем первое присваивание, ответ был: > "А вдруг поле не найдется"
Это просто скорее всего человек джавист.
Кстати навеяло ещё вопрос. Нужно ли тут оставить OutInt:=0; ? Или обнулять должен Slot принимающий эмитированный сигнал?
procedure ReadInt(var OutInt:Integer); var str:String; begin repeat Read(str); until (IsNumber(str) or IsEndOfRead or IsTermitateChar(Ch) or IsFullString(OutStr)); if IsNumber(str) then OutInt:=StrToInt(Str) else begin OutInt:=0; emitFirstSignal(@ReadInt, @OutInt, nil); end; end;
-
> Нужно ли тут оставить OutInt:=0; ? Или обнулять должен Slot > принимающий эмитированный сигнал?
Это как по контракту. Т.е. по спецификации слота.
-
> Это как по контракту. Т.е. по спецификации слота.
О точно. У эмитора есть контракт. Спасибо, переписал так.
Goal:=0; emitFirstSignal(@ReadInt, @OutInt, @Goal); OutInt:=Goal;
-
Тимохов Дима © (03.06.17 12:57) [29] > Иногда - нужен, иногда - не нужен. Зависит от ситуации. > > > В VCL пример есть. Вот, например DBTables.pas -> TDatabase. > Execute, или StdCtrls.pas -> TCustomListBox.ItemRect. > Факт - есть примеры использования FillChar для очистки результата > типа record.
2006: function TCustomListBox.ItemRect(Index: Integer): TRect;
var
Count: Integer;
begin
Count := Items.Count;
if (Index = 0) or (Index < Count) then
Perform(LB_GETITEMRECT, Index, Longint(@Result))
else if Index = Count then
begin
Perform(LB_GETITEMRECT, Index - 1, Longint(@Result));
OffsetRect(Result, 0, Result.Bottom - Result.Top);
end else FillChar(Result, SizeOf(Result), 0);
end; Тут - по делу. В твоем коде не по делу. Ты очищаешь два поля записи, а потом им же присваиваешь значения. Все эти заделы на будущее - всегда лишняя и ненужная головная боль для автора и читающих, будь проще. Keep it simple, Syndey! Вот в XE5 написали гораздо понятнее: function TCustomListBox.ItemRect(Index: Integer): TRect;
var
Count: Integer;
begin
Count := Items.Count;
if (Index = 0) or (Index < Count) then
Result := GetItemRect(Index)
else if Index = Count then
begin
Result := GetItemRect(Index - 1);
OffsetRect(Result, 0, Result.Bottom - Result.Top);
end
else
Result := TRect.Empty;
end;
-
> procedure ReadInt(var OutInt:Integer);
Дальше пост можно не читать. Калверта зубрить наизусть!
-
> Калверта зубрить наизусть!
У меня нет его книг. Не могли бы уточнить какую именно книгу вы имеете в виду?
-
> Игорь Шевченко © (03.06.17 22:40) [35]
и вообще не надо принимать всё так близко к сердцу. На самом деле это черновик. OutInt элементарно заменяется на value просто это я себе напоминалку оставил. Теперь когда разобрался что есть var и какой контракт у эммитора можно смело заменить на value.
-
|