-
У меня в программе некоторые объекты имеют счетчик использования. Сделано это для того, что бы они не были удалены до того, когда на них перестанут ссылаться другие объекты. Сначала пробывал добавить следующий код в деструктор:
destructor TGraphicObject.Destroy;
begin
if UseCount > 0 then
begin
FMustBeFree := true;
Exit;
end;
...
Но практически сразу же получал AV. Поэтому создал метод Free;
procedure TGraphicObject.Free;
begin
if Assigned(Self) then
if UseCount > 0 then
FMustBeFree := true
else
inherited; end;
Пока вроде бы проблем не наблюдается, но как-то беспокойно на душе :) Собственно вопросы: 1) Destroy в любом случае удаляет объект, даже если там стоит Exit и не вызывается inherited? 2) Метод Free не помечен как virtual, соответсвенно и мой метод не может быть отмечен как override. Безопасно ли использовать такой способ? Или правильней будет создать некий MyFreeMethod, где будет проверяться FUseCount и вызываться Free?
-
procedure TGraphicObject.Free; begin if Assigned(Self) then
гениально.
-
А оунер этого волшебного объекта в курсе что кто-то там что-то там считает?
:)
-
тебе надо посмотреть, как работает TInterfacedObject._Release - оно так примерно и делает, если ссылок 0, то вызывает Destroy
Или переопределить метод FreeInstance
-
Поросенок Винни-Пух © (19.06.08 20:04) [1]
> if Assigned(Self) then > > гениально.
Тебе никогда не встречался Self=nil ?
-
Мне интересно куда он там мог деться в первой же строчке собственного метода, что его проверяют на нил
-
Сделано это для того, что бы они не были удалены до того, когда на них перестанут ссылаться другие объекты.
То есть есть самодельный механизм подсчета и зачем-то переделываются методы дестрой и фри.
А для чего? Для того, чтобы можно было в любой строчке собственного когда неглядя вызвать фри объекта, не опасаясь что он будет удален если на него есть ссылки? А не логичнее ли вызывать фри по условию, если уж автору известно есть ссылки или нет их?
-
> Мне интересно куда он там мог деться в первой же строчке > собственного метода, что его проверяют на нил
var
g: TGraphicObject;
begin
g := nil;
g.Free;
end; Что произойдет в g.Free , если if Assigned(Self) не делать?
-
ты во внутрь самого фри не попадешь при таком раскладе
-
> ты во внутрь самого фри не попадешь при таком раскладе
Free - это статический метод (фактически обычная процедура). Почему же я в нее не попаду?
-
> Loginov Dmitry (19.06.2008 22:53:07) [7]
А зачем его делать? Советую взглянуть генофонд или прочитать справку.
-
Что произойдет в g.Free, если if Assigned(Self) не делать?
Произойдет то же самое, что происходит если делать if Assigned(Self)
g := nil; g := T...Create(); g.Free;
-
Нагляднее так:
type ttt = class procedure test; end;
procedure ttt.test; begin if Assigned(Self) then ShowMessage('yes') else ShowMessage('no'); end;
procedure TForm1.Button1Click(Sender: TObject); var t : ttt; begin t := nil; t := ttt.Create; t.Free; t.test; end;
-
> А зачем его делать?
У автора реализован собственный метод Free. В нем выполняется проверка if Assigned(Self). Что произойдет в g.Free (из [7]), если if Assigned(Self) (в TGraphicObject.Free) не делать?
-
> [0] ggg (19.06.08 19:39)
> if Assigned(Self) then > if UseCount > 0 then
в данном коде смущает то, что большое количество вложенных условий делает код запутанным. imho, уместнее if not Assigned(Self) then
Exit;
-
У автора реализован собственный метод Free. В нем выполняется проверка if Assigned(Self). Что произойдет в g.Free (из [7]), если if Assigned(Self) (в TGraphicObject.Free) не делать?
произойдет все то же самое если её делать.
-
> imho, уместнее > if not Assigned(Self) then > Exit;
имхо, нагляднее так: procedure TGraphicObject.Free;
begin
if Assigned(Self) then
begin
if UseCount > 0 then
FMustBeFree := true
else
inherited; end;
end; Но у каждого будет свое имхо и спорить, имхо, бессмысленно.
-
> произойдет все то же самое если её делать.
Для чего тогда, по Вашему, в TObject.Free() реализована такая же проверка?
-
я ж нарисовал пример в котором assigned рапортует "yes" и типа после этого метод уверен, что можно что-то там делать.
-
> я ж нарисовал пример в котором assigned рапортует "yes" > и типа после этого метод уверен, что можно что-то там делать.
совать во Free() битые ссылки - ситуация ненормальная и естественно карается. А вот вызов TObject(nil).Free - это обычное дело, и без проверки на nil не обойтись.
-
>> [1]system.pas
procedure TObject.Free;
begin
if Self <> nil then
Destroy;
end;
Вы считаете это глупость? >> [3]FreeInstance вызывается после Destroy, но если проверку добавить в оба метода, то да. Спасибо, помогло :) >> [6]Да, иметь возможность вызвать метод Free в любой момент не заботясь о последствиях весьма удобно. Заменить это уменьшением UseCount.. не безопасно. Просто, возможно несколько условий на различных стадиях работы движка, когда объект необходимо удалить. Тогда при выполнении нескольких условий счетчик может стать равным 0 до того, как объект действительно освободится. >> [14]Где-то встречал, будто опыты показали, что if...else работает быстрее, чем Exit. Не ручаюсь за достоверность, но большой разницы нет. >> [16]Насколько мне известно, эти begin..end дадут несколько другой код после компиляции, который будет выполнятся дольше. Хотя, возможно, это предрассудки моего препода по паскалю :)
-
> Насколько мне известно, эти begin..end дадут несколько другой > код после компиляции, который будет выполнятся дольше
Разговор про наглядность, а не про скорость. Скорость тут дело десятое.
> Хотя, возможно, это предрассудки моего препода по паскалю > :)
+1 :)
-
> ты во внутрь самого фри не попадешь при таком раскладе
я попаду в любой невиртуальный метод
-
Ну как бы всё-равно проблемы остались -- одну и ту же проверку приходится производить дважды: в Destroy и в FreeInstance. Если есть еще предложения, буду рад выслушать.
-
> [20] ggg (20.06.08 06:03)
> Где-то встречал, будто опыты показали, что if...else работает > быстрее, чем Exit. Не ручаюсь за достоверность, но большой > разницы нет.
ох уж эта привычка применять тонкую оптимизацию где попало, а потом разгребаешь if then if then if then
и еще тележку else if
|