На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
Страницы: (4) 1 [2] 3 4  все  ( Перейти к последнему сообщению )  
> Свойство-массив. Как правильно написать метод Free?
    Цитата ttiger @
    Перед тем, как повторно запускать подсчитывающий метод я "освобождаю" и снова создаю объект желаю таким образом очистить существующий, если есть и создать новый. Без явных доп. проверок.

    Может проще задать метод Clear для очистки ? Если эти массивы используются в некотором классе, то можно не париться и сразу создавать их в конструкторе этого класса, а для очитски юзать Clear

    Цитата ttiger @
    Хотелось удобства добавления в конец массива как в StringList. Раз все молчат, значит, не изобрел

    Для "тупого" добавления элемента достаточно написать одну процедуру
    ExpandedWrap disabled
      procedure AddToDynArray(var arr:TInt64DynArray;value:Int64); //overload;
      begin
        SetLength(arr,Length(arr)+1);
        arr[Length(arr)-1]:=value;
      end;

    Поэтому создавать класс имеет смысл именно для устранения тупого наращивания длины массива при каждом добавлении элемента. А для этого нужно использовать принципы, заложенные в TList\TStringList, а именно разделить понятия емкости массива (Capacity) и текущего числа элементов в массиве (Count).
    Сообщение отредактировано: leo -
      CodeMonkey, скажем так, для меня само повторное использование переменных - занятие нехорошее, по возможности стараюсь так не делать, а FreeAndNil соблазняет. Наверное поэтому и недолюбливаю. Второе: использовать FreeAndNil нужно аккуратно, потому что несмотря на название, там сначала происходит обнуление ссылки, а потом вызов Free. Если в деструкторе или методах из него вызванных нам ссылка нужна - приплыли. Сейчас точно не вспомню подробностей, но с такой ситуацией однажды сталкивался. Так что лучше все-таки задумываться, когда пишешь FreeAndNil, чем везде писать бездумно.
        Цитата --Ins-- @
        Если в деструкторе или методах из него вызванных нам ссылка нужна - приплыли.

        Это как раз плюс. Помогает отловить плохие ситуации. Потому что в описываемой тобой ситуации у тебя идёт ссылка через переменную, а не через Self. Заодно и избавимся от плохого стиля.

        Цитата --Ins-- @
        а FreeAndNil соблазняет

        Эээ... чем соблазняет? :) Что Free, что FreeAndNil - я не вижу разницы для повторного использования переменной.

        Цитата --Ins-- @
        само повторное использование переменных - занятие нехорошее

        Речь может идти не только о повторном использовании. Например, всевозможные ситуации типа "удалить объект, если его ещё не удалили".
          Для меня всегда FreeAndNil был скорее редким исключением, нежели правилом. Локальные объекты освобождаются с помощью Free в секции finally, поля-объекты - исключительно в деструкторе. Вопрос "удалить объект, если его еще не удалили" не стоит, скорее возникает ситуация "удалить объект, даже если его не создали".

          CodeMonkey, сам вопрос достаточно интересен. Приведи, пожалуйста, небольшой пример оправданного использования FreeAndNil, моя точка зрения вполне может оказаться не самой верной :)
            Цитата CodeMonkey @
            Потому что в описываемой тобой ситуации у тебя идёт ссылка через переменную, а не через Self. Заодно и избавимся от плохого стиля.


            Все может быть сложнее. Почему именно переменная? Поле класса. Мы его занулили, потом вызвали деструктор, а внутренний класс может что-то потребовать у внешнего, в т.ч. через это поле.

            Добавлено
            Цитата Domino @
            Для меня всегда FreeAndNil был скорее редким исключением, нежели правилом. Локальные объекты освобождаются с помощью Free в секции finally, поля-объекты - исключительно в деструкторе. Вопрос "удалить объект, если его еще не удалили" не стоит, скорее возникает ситуация "удалить объект, даже если его не создали".


            Вот и у меня точно так же.
              Цитата --Ins-- @
              Поле класса. Мы его занулили, потом вызвали деструктор, а внутренний класс может что-то потребовать у внешнего, в т.ч. через это поле.

              А зачем это внешнему классу что-то требовать у своего поля в момент удаления этого поля? По-моему, это логическая ошибка в явном виде (обращение к объекту в момент его удаления, т.е. к частично-инициализированному объекту). И вот использование FreeAndNil как раз позволит отловить такие ситуации. Конечно, такая ситуация может быть заранее предусмотрена, но это совершенно некрасиво (шаг в сторону, любое изменение кода "не в тему" и ваш код перестанет работать). В любом случае, такая ситуация не плавающая и обнаружится сразу же. После чего вы спокойно вернёте Free на место.

              Цитата Domino @
              Для меня всегда FreeAndNil был скорее редким исключением, нежели правилом. Локальные объекты освобождаются с помощью Free в секции finally, поля-объекты - исключительно в деструкторе

              Это слишком простая ситуация :) Если ВЕСЬ код действительно выглядит только так (и вы абсолютно точно в этом уверены, плюс исключаете всякую модификацию кода) - то большого смысла в FreeAndNil нет.

              Цитата Domino @
              Приведи, пожалуйста, небольшой пример оправданного использования FreeAndNil

              Не очень понятно, какого рода пример тут можно привести. Ведь использование FreeAndNil вместо Free - это же совершенно опциональное действие. Не считая запутанных примеров (ну вот Ins дал про обращение в момент удаления), один и тот же корректный код будет работать совершенно одинаково, что с Free, что с FreeAndNil.
              FreeAndNil чем-то подобен ремням безопасности: если прогон прошёл в штатном режиме - они не пригодились. Но если ваш код где-то напутал в последовательности действий, то FreeAndNil (как и ремни безопасности) защитят вас от последствий. Обнулив ссылку, FreeAndNil поможет поймать левое обращение сразу же, на месте. Без него код мог продолжить своё выполнение и дать неверный результат без возбуждения ошибки. Это опасно.

              Как я уже сказал, с учётом чрезвычайно низких накладных расходов на FreeAndNil вместо Free лично я НЕ вижу довода против него.

              Добавлено
              Вы мне лучше приведите пример оправданного использования Free :D
                Domino, --Ins--
                Не нужно перегибать палку ;) И "повторное использование переменных" может использоваться довольно часто и соотв-но поля-объекты могут уничтожаться не только "исключительно в деструкторе". Типичный пример - "одноразовый" объект типа TThread, второй раз его (легально) не используешь, нужно уничтожать. Поэтому если за время жизни объекта-контейнера объект-поток может создаваться несколько раз, то соотв-но после его уничтожения соответсвующее поле нужно занулять. Аналогично при очистке\ресете состояния контейнера часть его полей-объектов может также очищаться (Clear, Reset и т.п.), а часть может и уничтожаться с занулением ссылок - все зависит от ситуации и конкретики.

                Но рекомендовать повсюду совать FreeAndNil вместо Free - это ес-но перебор, хотя ничего ужасного в этом тоже нет и упираться изо всех сил, доказывая обратное я бы не стал ;)
                  Цитата CodeMonkey @
                  Вы мне лучше приведите пример оправданного использования Free
                  Ну, как же без него? Ресурсы надо освобождать :)

                  Цитата leo @
                  Не нужно перегибать палку
                  leo, я и не перегибаю, даже наоборот. Я вовсе не являюсь яростным противником FreeAndNil (чего нельзя сказать, например, о конструкциях with и команде Exit ;)), даже использую его по необходимости. Услышал новую для себя точку зрения - повсеместное использование FreeAndNil вместо Free и захотел услышать доводы в пользу этого подхода.

                  Цитата CodeMonkey @
                  Как я уже сказал, с учётом чрезвычайно низких накладных расходов на FreeAndNil вместо Free лично я НЕ вижу довода против него.
                  CodeMonkey, рассуждения о накладных расходах оставим в стороне - сейчас не то время, чтобы настолько мелочно заботиться об экономии процессорных инструкций, это в любом случае не аргумент в пользу Free. Единственный плюс, какой я вижу - это AV по адресу 0 при обращении к уничтоженному объекту вместо малопонятных циферок и тем более непредсказуемых результатов выполнения. Это да, но и происходит такое только тогда, когда идет отступление от классического подхода - уничтожения объектов исключительно в деструкторе. Free пишу на автомате, не задумываясь. Писать на автомате FreeAndNil, хм... получаем более внятные ошибки и упрощается модификация кода.
                  Вообще, подход имеет право на жизнь, почему бы и нет? :) В ближайшее время надо будет опробовать.
                    Цитата Domino @
                    команде Exit

                    А чем Exit-то не угодил? Да и With. Просто надо грамотна их использовать, а не тыкать куда придется. Например Exit удобно использовать в процедурах, где сначала цикл, и в случае если все элементы коллекции нас устраивают - какие-то действия. Если же хотя бы один элемент не устраивает, то проще вызвать Exit, чем делать лишнюю переменную для проверки. Ну, а With тут, например:
                    ExpandedWrap disabled
                      with ListView1.Items.Add do begin
                        Caption := "Новый";
                        ImageIndex := 1;
                      end;

                    Чем опять же заводить временную переменную (если конечно еще каких-то дальнейших действий с созданным Item'ом проводить не будет в этой функции).
                      Что, опять холивар?!
                      Как можно быть противником чего-то в языке программирования? Говорить, что являешься противником with и exit - все равно что говорить, что является противником слов "вместе" и "выход". Или, например, слова "концептуальный". Попробуйте быть противником repeat :)
                      Как можно быть противником слов - непонятно. Да, употреблять слова не к месту и не особо понимая их смысл плохо. Но не употреблять вообще означает обеднять язык.
                      Помните? "Крепкое словцо, вовремя и к месту сказанное, облегчает душу. Частая ругань лишает ругательство смысла. Примечание: ругань не сделает карты хорошими, а ветер - попутным".
                      Все, что есть в языке, надо применять. Должно быть применение нужного оператора в нужном месте.
                        Цитата leo @
                        Но рекомендовать повсюду совать FreeAndNil вместо Free - это ес-но перебор

                        Ну а почему?

                        Вот все почему-то говорят: "зачем нам этот FreeAndNil? Ну не нужен он!" Хотя ни одного аргумента я так и не услышал. ИМХО, тут говорит скорее сила привычки, чем реальное положение дел.

                        Цитата Domino @
                        Free пишу на автомате, не задумываясь.

                        Вот она, сила привычки :) А вот у меня уже привычка писать FreeAndNil :) Тоже на автомате. Я себе даже Code Template на F + Tab забиндил: автоматом вставить FreeAndNil(Obj) и выделить Obj, чтобы я сразу впечатал имя переменной. Очень удобно.

                        Цитата Domino @
                        Ну, как же без него? Ресурсы надо освобождать

                        Имелось ввиду, аргументы на использование Free вместо FreeAndNil, конечно же.

                        Цитата Domino @
                        Это да, но и происходит такое только тогда, когда идет отступление от классического подхода - уничтожения объектов исключительно в деструкторе.

                        Нет, почему же. Представим, что в деструкторе объекта (объект-контейнер) мы удаляем объектное поле с помощью Free. В деструкторе этого поля вызывается виртуальный метод, который ничего не делает в базовом классе, а в каком-то далёком предке вызывает последовательность действий, которая приводит к вызову виртуального-же метода объекта-контейнера. Который, в свою очередь, в каком-нибудь далёком предке (ошибочно) обращается к нашему удаляемому полю. При этом, обращение проходит на ура, но общее состояние становится безвозвратно испорченным. Упс.
                        Почему я тут везде поставил виртуальные методы? Затем, чтобы нельзя было сказать: вот, смотрите, в моих классах нет нужды использовать FreeAndNil. Дело в том, что вы не можете этого знать! Кто-нибудь создаст наследника, в котором неаккуратно вызовет в деструкторе какой-нибудь метод, приводящий (быть может далеко косвенно) к чтению уже удалённых или находящихся в процессе удаления объектов. FreeAndNil защитит вас от такой ситуации, Free - нет.

                        К чему я всё это. Вот говорят (не только тут, на DK на меня тоже взбычились :) ): а вот в этой ситуации FreeAndNil - лишний! А чего ж вы тогда не используете вызов Destroy? Ведь Free во многих ситуациях тоже излишен.
                        Заметьте, что в 99% кода на Delphi деструктор объектов не вызывается вообще! Нас уже приучили использовать вызов процедуры Free. А ведь когда-то народ, просто привыкший везде писать Destroy, тоже кричал: "зачем нам этот Free? Не нужен он тут! Где надо, я сам всё поставлю!". Ну и что? Пишем же мы сейчас все Free? (ладно, вообще-то этот пример - не факт, а моя фантазия, т.к. я уже начал подзабывать - как оно там на самом деле было, в те времена. Но могу легко себе это представить, и, вроде бы, это кажется правдоподобным :D ).
                        Ну так вот я агитирую за то, чтобы сделать ещё шаг вперёд: использовать FreeAndNil вместо Free. Ведь польза от перехода Free -> FreeAndNil гораздо больше, чем польза от уже случившегося перехода от Destroy к Free.
                        В первом случае мы получаем авто-защиту от плавающих ошибок (это НЕ панацея, т.к. могут существовать множественные ссылки, но, тем не менее, существенный бонус). Во втором случае мы получили всего лишь возможность не писать явно if. Почему? Потому что если бы мы явно вызывали Destroy, вместо Free, то мы запустили бы деструктор с Self = nil, что немедленно привело бы к AV при первом же обращении к полю объекта. Ошибка совершенно не плавающая и легко отлавливается. Согласитесь, что бонус от первого перехода намного более существенен, чем бонус от второго.
                        Так почему же медлить? Почему бы, начиная с сегодняшнего дня, везде не использовать FreeAndNil вместо Free? Если вы сделаете это своей привычкой - вы ничего не потеряете, а, наоборот, приобретёте немалые бонусы.

                        Просто я не единожды сталкивался с трудно выловимыми багами в чужом коде со сложной иерархией классов. Потратив несколько часов на бесплодные попытки найти источник проблем "в лоб", просто тупо заменив все Free на FreeAndNil, проблема находилась сразу же (но вот над решением проблемы приходилось ещу долго думать).

                        Добавлено
                        Цитата Romkin @
                        Что, опять холивар?!

                        Это не холивар, мои аргументы неоспоримы :lool:
                          Цитата Profi @
                          А чем Exit-то не угодил? Да и With.


                          Сейчас кто-нибудь еще и goto вспомнит :D
                            Цитата Profi @
                            Да и With. Просто надо грамотна их использовать, а не тыкать куда придется.

                            Проблема в том, что вы никак это не объясните большинству программистов на Delphi, которые являются батоно-давителями и уж конечно не читают форумы/блоги/книги по программированию. With не страшен, скажем, вам или мне (хотя я тоже на нём обжигался), но он плох в целом для Delphi-сообщества.
                            Вон, си тоже безопасный язык, если грамотно его использовать. Проблема только в том, что если у вас есть возможность что-то сделать не правильно - это обязательно сделают неправильно! Поэтому ситуация с сями и with больше похожа на обезьяну с гранатой. Это - тень из прошлого, когда господствовала идеология "мы даём программисту в распоряжение самые мощные инструменты, а он обязуется использовать их верно". История показала несостоятельность и наивность такой точки зрения. Поэтому в последние годы курс меняется на "если вы не хотите делать правильно - вас заставят это делать" (и это не только в программировании). И это правильно. Разработчики Delphi уже давно выкинули бы этот with, если бы.... не совместимость со старым кодом.

                            P.S. Что не так с exit - я пока ещё сам не понял :D
                              Цитата CodeMonkey @
                              ИМХО, тут говорит скорее сила привычки, чем реальное положение дел.


                              Соглашусь, скорее всего. Ну, а чтобы менять привычку причина должна быть очень веской. ;)

                              Цитата CodeMonkey @
                              Ведь польза от перехода Free -> FreeAndNil гораздо больше, чем польза от уже случившегося перехода от Destroy к Free.


                              Зря недооцениваешь преимущества Free перед Destroy. Free вместо Destroy писать обязательно в деструкторе класса. Почему? Потому что никто не отменял исключения в конструкторе. При исключении в конструкторе деструктор вызывается автоматом, а если ссылка на тот момент еще не инициализирована, то ловим новое исключение - AV. Ну, а учитывая что (по крайней мере у меня) 90% вызовов Free стоит именно в деструкторах, то это очень даже актуально. Так что не стал бы так оценивать пользу.

                              Добавлено
                              Цитата CodeMonkey @
                              что если у вас есть возможность что-то сделать не правильно - это обязательно сделают неправильно!


                              Кстати, с этой фразы начинается сборник законов Мерфи :yes:
                                Цитата --Ins-- @
                                Сейчас кто-нибудь еще и goto вспомнит

                                Хотя про goto в целом справедливо всё то же, что и для with, но сегодня goto не злоупотребляют вообще (можете привести пример из практики?), в отличие от with. Ну а раз не злоупотребляют - то какой же от него вред?
                                Если уж совсем жёстко - то его бы убрать (следуя той же логике "потенциально опасен"), но тут уже я против - сам его использую иногда :) Позволяет красиво выйти из нескольких циклов, не вводя процедуру или переупорядочивая код.
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (4) 1 [2] 3 4  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0551 ]   [ 15 queries used ]   [ Generated: 19.07.25, 05:48 GMT ]