Конференция "Прочее" » Что выдаст функция
 
  • 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:30) [20]
    > > Тимохов Дима ©   (02.06.17 14:15) [19]
    > интересно другое, FillChar зачем?


    // Дабы не оставить возможные новые члены
    // не инициализированными инициализируем нулям.



    ибо
    // Потенциально могут добавляться члены.

  • Sha © (02.06.17 14:41) [22]
    > Тимохов Дима ©   (02.06.17 14:37) [21]

    так лучше не делать,
    ибо потенциально это может привести к затиранию нулем указателя на строку
    и, как следствие, к утечке памяти
  • Тимохов Дима © (02.06.17 14:48) [23]

    > 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;

  • Sha © (02.06.17 16:12) [24]
    > Тимохов Дима ©   (02.06.17 14:48) [23]
    > Если уж очень мне надо сохранить функционал FillChar

    а тут тоже FillChar не нужен,
    т.к. благодаря магии компилятора R будет проинициализирована
  • Тимохов Дима © (02.06.17 16:23) [25]

    > Sha ©   (02.06.17 16:12) [24]
    > > Тимохов Дима ©   (02.06.17 14:48) [23]
    > > Если уж очень мне надо сохранить функционал FillChar
    >
    > а тут тоже FillChar не нужен,
    > т.к. благодаря магии компилятора R будет проинициализирована

    и даже Integer? )))
  • Sha © (02.06.17 16:29) [26]
    а нафига его инициализировать, если это никогда не приведет к ошибке?
  • Тимохов Дима © (02.06.17 16:45) [27]

    > Sha ©   (02.06.17 16:29) [26]
    > а нафига его инициализировать, если это никогда не приведет
    > к ошибке?

    Предпочитаю не оставлять неинициализированные переменные.
  • Игорь Шевченко © (03.06.17 10:35) [28]
    FillChar не нужен более чем совсем, во-первых, он не делает ничего полезного, во-вторых затрудняет понимание кода.

    В свое время бывший коллега (ныне покойный) писал такой код:

    A := 0;
    A := FieldByName('B').AsInteger;

    Когда его спросили, зачем первое присваивание, ответ был: "А вдруг поле не найдется"
  • Тимохов Дима © (03.06.17 12:57) [29]

    > Игорь Шевченко ©   (03.06.17 10:35) [28]
    > FillChar не нужен более чем совсем, во-первых, он не делает
    > ничего полезного, во-вторых затрудняет понимание кода.


    Иногда - нужен, иногда - не нужен. Зависит от ситуации.

    В VCL пример есть. Вот, например DBTables.pas -> TDatabase.Execute, или StdCtrls.pas -> TCustomListBox.ItemRect.
    Факт - есть примеры использования FillChar для очистки результата типа record.

    Еще раз: FillChar(Result,...) - это способ дать умолчательное значение для результата типа Record. Но этот способ таит в себе тонкости, которые надо знать начинающим программистам, которые еще не сталкивались с подобными тонкостями. Собственно, я для этого и написал свой комментарий выше.
  • Pavia © (03.06.17 21:20) [30]
    Вообще-то FillChar как раз и нужен
    Если его не сделать то в первом коде в первом рекорде будет инвалидный указатель.
  • Pavia © (03.06.17 21:26) [31]

    > Когда его спросили, зачем первое присваивание, ответ был:
    >  "А вдруг поле не найдется"

    Это просто скорее всего человек джавист.

    Кстати навеяло ещё вопрос.
    Нужно ли тут оставить 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;
  • Тимохов Дима © (03.06.17 21:56) [32]

    > Нужно ли тут оставить OutInt:=0; ? Или обнулять должен Slot
    > принимающий эмитированный сигнал?

    Это как по контракту. Т.е. по спецификации слота.
  • Pavia © (03.06.17 22:39) [33]

    > Это как по контракту. Т.е. по спецификации слота.

    О точно. У эмитора есть контракт. Спасибо, переписал так.

        Goal:=0;
        emitFirstSignal(@ReadInt, @OutInt, @Goal);
        OutInt:=Goal;
  • Игорь Шевченко © (03.06.17 22:39) [34]
    Тимохов Дима ©   (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;

  • Игорь Шевченко © (03.06.17 22:40) [35]

    > procedure ReadInt(var OutInt:Integer);


    Дальше пост можно не читать. Калверта зубрить наизусть!
  • Pavia © (03.06.17 22:49) [36]

    > Калверта зубрить наизусть!

    У меня нет его книг. Не могли бы уточнить какую именно книгу вы имеете в виду?
  • Pavia © (03.06.17 23:16) [37]

    > Игорь Шевченко ©   (03.06.17 22:40) [35]

    и вообще не надо принимать всё так близко к сердцу. На самом деле это черновик. OutInt элементарно заменяется на value просто это я себе напоминалку оставил. Теперь когда разобрался что есть var и какой контракт у эммитора можно смело заменить на value.
  • Игорь Шевченко © (04.06.17 10:44) [38]
    Pavia ©   (03.06.17 22:49) [36]

    https://edn.embarcadero.com/article/10280
 
Конференция "Прочее" » Что выдаст функция
Есть новые Нет новых   [134430   +4][b:0][p:0.002]