-
Всем привет! Возможно ли сделать так, чтобы объект при уничтожении сам себе присваивал nil? Или надо FreeAndNil использовать?
-
Не туда запостил. Сорьки.
-
> чтобы объект при уничтожении сам себе присваивал nil?
Прикольно, трупы сами себе могилу роют.
-
Как объект может себе нил присвоить? "Это же памятник" (с) ))
-
должен быть специальный "зомби" агент, т.е. объект... он должен знать адрес своей переменной в единственном экземпляре, и перекрытый деструктор в котором он типа на последнем издыхании... оп и присваивает.
> Или надо FreeAndNil использовать? это проще всего.
-
А если у нас два указателя на один и тот же объект?
-
>А если у нас два указателя на один и тот же объект? У меня как раз такой случай. В одном объекты, а в другом ссылки на объекты. Я по ссылкам удаляю объекты.
-
Пока сделал удаление по ссылке:
procedure FreeAndNil(AObj: PObject); begin if PObject(AObj)^ <> nil then begin PObject(AObj)^.Free; PObject(AObj)^ := nil; end; end; Но AutoNil конечно же предпочтительней. На мой взгляд такое возможно. Будем думать.
-
Короче надо свой ТОбжект писать. После FreeInstance это вполне возможно сделать, если есть внутренний массив со счетчиком и указателями ссылок.
-
> В одном объекты, а в другом ссылки на объекты. чудеса бывают
-
> ухты © (10.12.18 19:29) [9]
иногда бывает полезно
-
полезно что? 2 списка? это совсем не америка
-
совсем америка случается совсем редко
иногда бывает полезно работать с объектами через ссылки
-
а как без ссылок?
-
В общем сделал 2 варианта. 1-й указываем адрес переменной объекта
procedure TZObject.Free(AObj: PObject); begin inherited Free; PObject(AObj)^ := nil; end; а второй почти тоже самое.
procedure FreeAndNil(AObj: PObject); begin if (AObj <> nil) then if (PObject(AObj)^ <> nil) then begin PObject(AObj)^.Free; PObject(AObj)^ := nil; end; end;
Оба работают.
-
как обычно - доступ к данным через адрес данных
а когда нужен дополнительный уровень косвенности, работают с данными через адрес адреса данных
-
Ну так при чем тут ссылки и работа с объектами ? )))
-
не видишь суслика? а он есть )
-
>Ну так при чем тут ссылки и работа с объектами ? ))) Удобство управления для объектов созданных в разных местах. У вас просто такой случай не попался, а в сложных системах ссылки - это вообще норма.
GenerateScene(1750, False, False); //<-Тут 1750 объектов добавилось
LoadObj(GC_MODELSPATH + '...', RT, @ZCam, @gObject); //<- +1 объект LoadObj(GC_MODELSPATH + '...', RT, @ZCam, @gVarious); //<- +1 объект
Init3DGrid(@gGrid, 33, 50, RT, @ZCam); //<- +1 объект //Ссылки на объекты Scene.AddObject(@gObject); Scene.AddObject(@gVarious); Scene.AddObject(@gGrid);
// Работаем с объектами, // а потом бац и по ссылкам удаляем все объекты Scene.DestroyObjects;
// nil - просто индикатор удаленности
-
Так это выглядит в коде. Просто и удобно. Особенно когда объектов тысячи. И все внешние переменные = nil.
procedure TZObject.Free(AObj: PObject); begin inherited Free; PObject(AObj)^ := nil; end;
procedure TZObjectsArray.DestroyObjects; var i: Integer;
begin for i := Low(FObjects) to High(FObjects) do begin FObjects[i]^.Free(@FObjects[i]); end;
SetLength(FObjects, 0); FNumObjects := 0; end;
-
У меня переменные многократно используются. То удаляются, то добавляются. Можно сильно запутаться, а так жесткая напоминалка об обнулении. И от класса объекта не зависит никак. И код сократился в разы - не надо помнить где и какой объект инициализирован.
//Вариант 0 (Как было) gVariant.Free; gVariant := nil; gObject.Free; gObject := nil; gGrid.Free; gGrid := nil;
//Вариант 1 FreeAndNil(@gVarious); FreeAndNil(@gObject); FreeAndNil(@gGrid);
//Вариант 2 gVarious.Free(@gVarious); gObject.Free(@gObject); gGrid.Free(@gGrid);
//Вариант 3 (самый удобный) Scene.DestroyObjects;
-
> dmk © (10.12.18 12:26) > > Всем привет! > Возможно ли сделать так, чтобы объект при уничтожении сам > себе присваивал nil?
Никакой объект не имеет "объективной" возможности узнать сколько пользовательская программа сделала на него ссылок. Так что вопрос дурной. Вторая "дурность" вопроса заключается в самой "якобы" необходимости обниливать какую-то ссылку.
-
Это конечно ИМХО, но вполне обоснованное.
-
> Германн © (11.12.18 02:49) [22]
чем-то это мне напоминает борьбу с GOTO )
-
procedure TZObject.Free(AObj: PObject);
А вот зачем указатель? TObject - уже указатель на объект же. Точно требуется еще и указатель на этот указатель?
-
Если хочется переприсвоить значение самой переданнйо переменной - её просто надо передать по ссылке, т.е.
procedure TZObject.Free(var AObj: TObject);
Как-то оно прямее, понятнее, добрее
-
>А вот зачем указатель? У меня массив указателей на переменные, а не на адреса объектов. Инчае в параметрах придется писать обертку PObject(MyObjectType), а он не пропустит, т.к. строгая типизация, а указатели пропускает. Я уже все варианты перепробовал. Так проще всего:
type PVar = ^TVar; TVar = Pointer;
procedure TZObject.Free(AVar: TVar); begin inherited Free;
//Очистка переменной if (AVar <> nil) then if (PVar(AVar)^ <> nil) then PVar(AVar)^ := nil; end;
и вызов
FObjects[i].Free(@FObjects[i]^); Все внешние переменные прилинкованные к массиву обнуляются и освобождаются.
-
Добавляем ссылку на переменную:
Scene.AddObject(@gObject); Удаляем ссылку из массива указателей^
FObjects[i].Free(@FObjects[i]^); Освобождаем объект и очищаем переменную:
FreeAndNil(@gVarious);
Очистка:
procedure FreeAndNil(AVar: TVar); begin if (AVar <> nil) then if (PVar(AVar)^ <> nil) then begin PObject(AVar)^.Free; PVar(AVar)^ := nil; end; end;
-
У меня массив не FObjects: array of TZObject, а FObjects: array of PZObject; Ссылки на переменные и на другие массивы, которые уже TZObject.
-
> dmk © (11.12.18 11:49) [26] > Все внешние переменные прилинкованные к массиву обнуляются и освобождаются.
Чего??
> dmk © (11.12.18 12:08) [28] > У меня массив не > FObjects: array of TZObject, а > FObjects: array of PZObject;
Это понятно, про это и вопрос.
> dmk © (11.12.18 12:08) [28] > Ссылки на переменные и на другие массивы, которые уже TZObject.
Но зачем? вот что мне не понять. Обратите внимание: в VCL не смотря на то, что есть понятие "владелец объекта", который этот объект удаляет, кстати, совершенно успешно, и при всём при этом в VCL никаких PObject - нет совершенно. Ибо не нужны они. Правда-правда.
-
> dmk © (11.12.18 11:55) [27]
Если честно - дичь какая-то. Если бы вы обрисовали задачу, которую всеми этими изворотами решаете - уверен, вам бы подсказали более прямой и понятный путь решения задачи.
Это уже не говоря про то, что FreeAndNil() есть штатная же, и она иначе несколько устроена в смысле типов
-
>Если бы вы обрисовали задачу, которую всеми этими изворотами решаете - >уверен, вам бы подсказали более прямой и понятный путь решения задачи. В [18] описаны варианты создания объектов. Из файла [1], процедурная генерация [2], генерация массивов [3]. Над объектами проводится куча действий: 1. Трансформация 2. Перекраска 3. Текстурирование 4. Слияние 5. Отрисовка и т.д. и т.п. Действия в цикле однотипные, но доступ к объектам или через массив ссылок или через переменную. Нужно и так и так. Кол-во объектов может быть и сотни и тысячи и десятки тысяч. Переменных может быть также несколько десятков. Зачем мне листинги с удалением персональных переменных? Проще добавить в массив и потом махом все удалить. Поведение объектов хаотичное. Это 3D-сцена в общем. По ссылкам в массиве удобно все удалить или удалить выборочно.
-
Из написанного вами вот что не понятно: зачем массив указателей на (сслыки) объекты? Да, я умышлено пишу "ссылки на объекты", ибо TObject - эти именно ссылка на объект по своей сути, ну или, более честно, указатель. Уже указатель!
> Действия в цикле однотипные, но доступ к объектам или через массив ссылок или через переменную.
Это вы так сделали, и это из кода видно. Но зачем? смысл какой всего этого? зачем вам ссылки непременно понадобилось в разных местах хранить? Кстати, почему бы не хранить целочисленные индексы в массиве объектов? зачем указатели? Индексы имеют тот плюс, что их можно контролировать. А указатели - нельзя, т.к. нет возможности достоверно узнать указывает указатель на валидное значение или на невалидное в памяти.
-
-
Не понятно (мне), но определённо красиво! )
PS Расширение для файла .obj - режет глаз, конечно (ибо уже имеет своё устоявшееся значение в компьютерном мире). Но чем заменить - не знаю.
-
>.obj - режет глаз Зато бесплатно. Это открытый формат. Бесплатных очень мало.
-
> массив указателей на переменные еще чудесатее а вот этот новый фри скорее всего напрочь и эту переменную стирает, прям из кода))
-
По ссылкам в массиве удобно все удалить или удалить выборочно.
а теперь я начинаю хотеть хранить ссылки на чудесный самоубивающийся класс в свойствах другого класса.
привет, тебе, пернатый архитектор у которого не болит голова.
-
> У меня массив указателей на переменные, а не на адреса объектов. повторю ранее говорившееся, читай внимательно - переменная объекта, это уже указатель. нет смысла в указателе на указатель, первый и так прекрасно на объект указывает, без дополнительных посредников. > Так проще всего: > type > PVar = ^TVar; > TVar = Pointer; > > procedure TZObject.Free(AVar: TVar); > begin > inherited Free; > > //Очистка переменной > if (AVar <> nil) then > if (PVar(AVar)^ <> nil) then PVar(AVar)^ := nil; > end;
... если нормально, то как мне кажется попроще, а делать будет то же самое. TObject вместо TVar чтобы, ты сам упоминал, без приведений типов, сойдет для всех потомков procedure TZObject.Free(var AVar: TObject);
begin
inherited Free;
AVar:= nil;
end;
-
> Прикольно, трупы сами себе могилу роют.
В нормальных языках это давно так реализовано.
> Возможно ли сделать так, чтобы объект при уничтожении сам > себе присваивал nil? > Или надо FreeAndNil использовать?
Нельзя. Embarcodere уже который год тянут кота за яйца, но автосборку мусора сделать не могут. Да проще свой препроцессор написать.
-
>sniknik © (11.12.18 20:40) [38] Так только для переменной подходит. Через PObject еще из массива освобождать можно. Где AVar - указатель на ячейку массива, а AVar^ доступ к переменной в ячейке, т.к. в ячейке хранится ссылка на другую переменную. Запутано конечно, но работает норм. В упрощенном виде: 1. Доступ к переменной - PVar(AVar)^. 2. Доступ к ячейке массива в которой хранятся ссылки на переменные - PObject(AVar^)^.
-
>Да проще свой препроцессор написать. Уже хочется свой компилятор если чесно. Куча ограничений кругом.
-
>Embarcodere уже который год тянут кота за яйца, но автосборку мусора сделать не могут. Они вам продадут эту фичу лет через 5 в версии 11.4. Это же маркетинг.
-
вы как переменные в ячйку запихали? ))
-
мое имхо, что можно делать, что хочешь, лишь бы тебе было понятно и полезно. domain specific language, ёлки.
-
>вы как переменные в ячйку запихали? )) Для этого надо 2 высших иметь. У вас есть 2 высших?
-
тут 2 мало, тут надо щтук пять а лучше шесь, но у меня семь, так что все в порядке
-
-
вы не обсуждаете а лепите. что то издалека напоминающее что то типа турбо паскаль )) со всвоими велосипедами в виде эти фри[энднил], ну и венцом из переменных в ячейках. и можно тольео повторить -
> дичь какая-то
-
> Sha © (11.12.18 09:24) [23] > > > Германн © (11.12.18 02:49) [22] > > чем-то это мне напоминает борьбу с GOTO )
Почему только напоминает? Это та же самая борьба только на другом фронте. :)
-
> Sha © (11.12.18 09:24) [23] > > > Германн © (11.12.18 02:49) [22] > > чем-то это мне напоминает борьбу с GOTO )
Ведь использование GOTO подразумевает использование Label, которые можно ставить в коде что в паскалевской, что в Дельфийской программе практически где угодно (возможно не везде, но я это не проверял). И IDE/Компилятор не могут уверенно указать на принципиальную ошибку алгоритма/программы. Т.о. вся ответственность за использование такого полностью ложится на его автора. Но готов ли автор её принять?
-
> Германн © (12.12.18 02:21) [50]
И GOTO, и FreeAndNil обычно не требуются программисту.
Но в тех редких случаях, когда их применение действительно имеет смысл, они способны существенно упростить алгоритм или повысить скорость.
-
>>sniknik © (11.12.18 20:40) [38]> Так только для переменной подходит. Через PObject еще из массива освобождать можно. да, я понял, у тебя в объекте указатель на себя же, на внешнюю переменную с собой(которая тоже указатель). по нему "обниляеш" именно внешнюю. поначалу сбило то, что ты в примере его во Free переменной передаешь, а не берешь из внутренних переменных. вообще, "претензия" к такому подходу только в том что это громоздко и сложно для понимания (самому через пару лет поменять понадобится...). лучше бы как то поменять логику, обойтись например без внешней вообще, работать со спискам объектов, в котором их уничтожение уже реализовано (приснопамятный сборщик мусора... ), ну вот, тут адрес внешний внутрь передается, но смысла в этом не вижу, если уж нужна для работы используй и бросай без Free, список потом сам позаботится. type
TMyObject = class(TObject)
Obj: TMyObject;
destructor Destroy; override;
end;
destructor TMyObject.Destroy;
begin
inherited;
Form1.Edit1.Text:= '!!!!!!'
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
ObL: TObjectList;
pO: TMyObject;
begin
ObL:= TObjectList.Create;
try
ObL.Add(TObjectList.Create);
ObL.Add(TObject.Create);
i := ObL.Add(TMyObject.Create);
pO:= TMyObject(ObL.Items[i]);
pO.Obj:= @pO;
finally
ObL.Free;
end;
end;
-
>вообще, "претензия" к такому подходу только в том >что это громоздко и сложно для понимания Так я без наставлений в народ вышел. Просто спросил, а меня уже запинали. У меня 3D-эшечка. 3D-объекты вещь комплексная и создаются у меня в разных местах и разными методами. Модифицируются также в разных местах и даже в разных модулях. Загружаются в массивы или переменные. Вот например, система частиц - это же массив созданных процедурно или загруженных из файла объектов. У них даже классы обработки разные. Только общий предок TZObject. Частицы находятся в одном массиве. Объекты взаимодействия в другом или вообще в отдельной переменной. У меня и так перерасход памяти жуткий идет, а вы мне предлагаете еще один массив с T-классом сделать. Двойное существование объекта в общем то не нужно. Поэтому я и придумал массив ссылок (сцена). Может как то иначе этот массив можно представить?
У меня так сделано:
type PZScene = ^TZScene; TZScene = class private FObjects: array of PZObject; FNumObjects: Integer; FSceneStatistic: TSceneStatistic; procedure SetObject(Index: Integer; Value: PZObject); inline; function GetObject(Index: Integer): PZObject; inline; public constructor Create; destructor Destroy; override; procedure AddObject(Value: PZObject); procedure ChangeTarget(ATarget: PBitmap64); procedure DeleteObject(Value: PZObject); procedure DestroyObjects; procedure DrawObjects; function GetMaxObjectsDepth: Single; function GetDepth: Single; procedure InverseDraw; function LowIndex: Integer; inline; function HighIndex: Integer; inline; function NumJoins: Integer; function NumPoints: Integer; function NumTriangles: Integer; function ObjectExist(Value: PZObject): Boolean; inline; function ObjectIndex(Value: PZObject): Integer; inline; procedure Reset; procedure SetFill(Value: Boolean); procedure SetStroke(Value: Boolean); procedure SetOpacity(Value: Single); procedure ScaleObject(Value: PZObject; F: Single); procedure ScaleObjects(Value: Single); procedure SetCheckerColors(Args: array of TColor32); procedure SetHSVColors(AOrient: TPlaneType); procedure SetObjectFirst(Value: PZObject); procedure SetRandomColors; procedure UpdateStatistic; //--- property Objects[Index: Integer]: PZObject read GetObject write SetObject; property NumObjects: Integer read FNumObjects; property Statistic: TSceneStatistic read FSceneStatistic; end;
procedure TZScene.AddObject(Value: PZObject); begin if (Value^ <> nil) then begin if not ObjectExist(Value) then begin Inc(FNumObjects); SetLength(FObjects, FNumObjects); FObjects[High(FObjects)] := Value; end; end; end;
procedure TZScene.DeleteObject(Value: PZObject); var i, k: Integer; Found: Boolean;
begin if (FNumObjects > 0) and (Value <> nil) then begin Found := False; k := LowIndex;
for i := LowIndex to HighIndex do begin if FObjects[i] = Value then begin FreeAndNil(@Value^); Found := True; Continue; end else //Пропустим удаленный объект begin FObjects[k] := FObjects[i]; Inc(k); end; end;//for
FNumObjects := k; SetLength(FObjects, FNumObjects);
//Если не найден, то удаляем объект вне сцены if (not Found) then FreeAndNil(@Value^); end; end;
procedure TZScene.DestroyObjects; var i: Integer;
begin if (FNumObjects > 0) then begin for i := Low(FObjects) to High(FObjects) do begin FObjects[i].Free(@FObjects[i]^); end;
SetLength(FObjects, 0); FNumObjects := 0; end; end;
Добавляются объекты в сцену так:
//Удаляем старый объект Scene.DeleteObject(@gObject);
//Создаем и загружаем файл LoadObj(OpenMeshDialog.FileName, RT, @ZCam, @gObject);
if gObject.Correct then begin Scene.AddObject(@gObject); Scene.SetObjectFirst(@gObject); end;
Потом сцена удаляется:
procedure TRenderForm.FreeScene; begin if bSceneActive then begin //Массив ссылок на Z-Объекты Scene.DestroyObjects;
//Объекты вне массива FreeAndNil(@gVarious); FreeAndNil(@gObject); FreeAndNil(@gGrid); FreeAndNil(@gFrustum);
//Кнопка загрузки FLoadBtn.Visible := False; FLoadBtn.Enable := False;
//Флаг использования 3D bSceneActive := false; end; end; Но мой вариант рабочий и вроде уже привык. Можно как то проще сделать? Буду рад услышать хорошие советы.
-
Мне nil понадобился, чтобы точно узнавать — инициализирован объект или нет. Если nil - то создаем в этой переменной или ячейке в массиве. У меня объекты динамически создаются/удаляются и какая переменная освободится заранее не известно. Вот здесь видно поведение объектов: https://yadi.sk/i/tU7G3tfHrl4hBQ
-
> Можно как то проще сделать? имхо конечно, но я как раз проще и посоветовал, работать со списком, стандартным. а не с массивом, и своим "велосипедом" по его обработке... ну, совсем без велосипеда не обойтись, но вот наследуй твой TZScene от TObjectList и у тебя сразу появятся стандартные методы по добавлению/удалению объектов, и "дестроить" их самому/следить за этим/за массивом не нужно будет, и т.д. много преимуществ/упрощений на мой взгляд. не, я конечно не совсем в теме, что у тебя там, со стороны не видно, вот к примеру зачем в 2-х местах ссылки? бери всегда из списка да и все. копию просто игнорь, в следующий раз если понадобится снова из списка, а nil-ов в нем попросту не будет, - стал не нужен объект, удалил из списка, а он уже сам его освободит... удобно.
-
>TObjectList Тут есть оговорка. VCL не используется. Почти чистый WinApi. Вплоть до своего менеджера памяти.
-
Какой феерический трындец.
> TObjectList > Тут есть оговорка. VCL не используется.
Можно посмотреть, как он реализован, не слишком сложная задача.
После просмотра этого:
>type > PZScene = ^TZScene; > TZScene = class
и этого:
>Вплоть до своего менеджера памяти.
у меня когнитивный диссонанс возникает.
Не дай бог такое приснится.
-
> pavia © (11.12.18 20:52) [39] > > > > прикольно, трупы сами себе могилу роют. > > в нормальных языках это давно так реализовано. > > > > возможно ли сделать так, чтобы объект при уничтожении сам > > себе присваивал nil? > > или надо freeandnil использовать? > > нельзя. > embarcodere уже который год тянут кота за яйца, но автосборку мусора сделать не могут. > да проще свой препроцессор написать. нормальный язык это где gc находит трупы и закапывает?
-
> Sha © (12.12.18 10:02) [51] > > > Германн © (12.12.18 02:21) [50] > > И GOTO, и FreeAndNil обычно не требуются программисту. > > Но в тех редких случаях, когда их применение действительно > имеет смысл, > они способны существенно упростить алгоритм или повысить > скорость.
Вот с этим я как раз и не спорил. Более того. У меня был случай, когда GOTO давал гораздо более понятный при просмотре/анализе/отладке код. А вот FreeAndNil никогда. Возможно потому, что у меня не достаточно было опыта.
-
> Sha © (12.12.18 10:02) [51] > > > Германн © (12.12.18 02:21) [50] > > И GOTO, и FreeAndNil обычно не требуются программисту. > > Но в тех редких случаях, когда их применение действительно > имеет смысл, > они способны существенно упростить алгоритм или повысить > скорость.
Не в службу, а в дружбу. А не затруднит-ли вас, Александр написать простой рабочий пример, где применение FreeAndNil хоть чем-то оправдано?
-
> где применение FreeAndNil хоть чем-то оправдано? часто использую для редко используемых форм, т.е. вот есть форма в проге которая используется редко, и после использования надолго не нужна, логично ее создавать перед использованием, и уничтожать после. nil в ее переменной это как индикатор, что нужно ее создать перед показом, что не висит она в данный момент в "фоне". конечно можно было бы ввести какой другой индикатор, но это было бы как то нелогично.
-
+ я выше не про саму функцию FreeAndNil, а про принцип, "занилять" формы проще просто присваиванием в деструкторе.
-
> sniknik © (13.12.18 10:19) [61]
> что нужно ее создать перед показом, что не висит она в > данный момент в "фоне".
Валидность ссылки легко проверяется по Screen.Forms.
FAN - MD ;)
-- Regards, LVT.
-
> Германн © (13.12.18 02:12) [60]
Обычно это массивы, списки, пулы, очереди и т.п. объектов, из которых долго или неудобно исключать адреса по одному, а гораздо удобнее обнилить или каким-то образом пометить адрес данных. А впоследствии перепаковать или освободить целиком весь контейнер.
В качестве второго примера - многоэтажные этажерки из вложенных try.
-
> Валидность ссылки легко проверяется по Screen.Forms. перебором массива сравнивая с несуществующей переменной формы, или по отсутствию текста с именем формы в существующих? вместо простого сравнения if ххх <> nil ... не не думаю, что это легко. оно конечно все относительно, и для "бешеной собаки 10 верст не крюк", но вот не хочется менять 2 строки кода, на ... да хотя бы на 3, хотя их явно будет побольше.
-
-
> Sha © (13.12.18 10:50) [64] > > > Германн © (13.12.18 02:12) [60] > > Обычно это массивы, списки, пулы, очереди и т.п. объектов
Примерно так я и думал. Задач, в которых нужны "массивы, списки, пулы, очереди и т.п. объектов у меня лично не было.
> sniknik © (13.12.18 16:35) [65] > > > Валидность ссылки легко проверяется по Screen.Forms. > перебором массива сравнивая с несуществующей переменной > формы А почему бы и нет? Ну не миллионы же у вас в списке Forms!
-
> sniknik © (13.12.18 16:35) [65]
> не не думаю, что это легко.
Ну, считай, что оно уже есть.
function AssignedFormVar(fv: TForm): Boolean; var i: Longint; begin Result := Assigned(fv); if Result then with Screen do for i := 0 to Screen.FormCount-1 do begin Result := (fv = Forms[i]); if Result then Break; end; end;
-- Regards, LVT.
-
> А почему бы и нет? а смысл? менять простое сравнение целочисленной переменной на цикл? ... > Ну не миллионы же у вас в списке Forms! а вот это тут совсем не причем.
> Ну, считай, что оно уже есть. круто.. весь проникся мудростью... сарказм. но в общем то функция ниуть не лечит ту болезнь от которой спасает/ремендуют использовать FreeAndNil. в итоге тот же вопрос - а смысл?
procedure TForm1.Button2Click(Sender: TObject); var form: TForm;
function AssignedFormVar(fv: TForm): Boolean; var i: Longint; begin Result := Assigned(fv); if Result then with Screen do for i := 0 to Screen.FormCount-1 do begin Result := (fv = Forms[i]); if Result then Break; end; end;
begin form:= TForm.Create(self); try //test - error if AssignedFormVar(form) then Edit1.Text:= 'Assigned' else Edit1.Text:= 'not Assigned';
form.Free; //FreeAndNil(form); if AssignedFormVar(form) then Edit2.Text:= 'Assigned' else Edit2.Text:= 'not Assigned'; finally form.Free; end; end;
-
> sniknik © (14.12.18 10:14) [69]
> но в общем то функция ниуть не лечит ту болезнь от которой > спасает/ремендуют использовать FreeAndNil.
Не совсем понял пример, но, видимо, д.б.
finally if AssignedFormVar(form) then form.Free; end;
-- Regards, LVT.
-
> Не совсем понял пример одно из того почему рекомендуют FreeAndNil вместо Free, как раз такая ситуация, не нужно доп.проверок. а тут от чего уходим к тому и пришли, только из-за желания использовать "крутой" метод проверки.
-
>только из-за желания использовать "крутой" метод проверки Но ведь других средств нет. Только проверка на nil. После FreeInstance образуется адресное пространство, которое может быть в зоне AV. Неудобная недоработка.
-
> Но ведь других средств нет. Только проверка на nil. она есть во Free которым уже все надрессированы пользоваться, "на автомате". осталось "передрессироваться" на использование FreeAndNil, и проблема "уйдет". пример вон выше, скопируй получи ошибку, а после раскоментарь/замени Free на FreeAndNil.
> Неудобная недоработка. эта, даже не знаю что сказать... вот прямо перед вами доработанное средство... или как говорил классик "разруха она в головах".
-
> sniknik © (14.12.18 15:55) [71]
> одно из того почему рекомендуют FreeAndNil вместо Free
FAN - MD. Костыль при кривом проектировании.
Особенно для форм, кои есть компоненты и, в случае удержания ссылок на оные, должно пользовать механизм Notification. Ну, или, на худой конец, массивом Forms, для отыскания утерянной формы.
Бо, и глобальные переменные - MD.
-- Regards, LVT.
-
> FAN - MD. Костыль при кривом проектировании. и че ты не консультант борланда был когда он и функцию безопасного обниления делал да проверку на нил во фри сувал, чуть ли не изначально при появлении генофонда... уж объяснил бы им ужо.
> должно пользовать механизм Notification. ага, особенно когда из потока к форме обращаешься т.е. нотификейшн перед нотификейшном, первый проверка есть ли она (только куда что посылать) второе собственно рабочее событие... ну очень удобно.
> Бо, и глобальные переменные - MD. вообще чего мелочится? программирование - MD. (аппликатион если чё тоже глобальная переменная)
з.ы. весь пост - сарказм. уже почему то по другому не получается. ведь все просто - есть возможность у языка, пользуйся, если к месту, удобно, нет "скрытых багов". нет же куча народу с догмами, того нельзя сего нельзя, и хоть бы что аргументированно... но нет, за аргументы выдают что-то по заковыристые, скоро 2 + 2 будут советовать не просто операцию использовать а что-то через COM-обьекты, микросервисы и т.д. еже с ними.
-
Фри реально костыль. )
-
и давно ты кошерный деструктор использовал? который не костыль. а вот была бы ява там подобное синтаксическим сахаром называют, ... а баги фичами...
-
Ну нет, синтаксический сахар это другое. Например тернарная операция или типа того. Кстати, буквально вот http://pda.delphimaster.net/?id=1542948910&n=3, в делфи ввели возможность объявление переменной "по месту" + определение типа в компайл тайм, вот это тоже сахар. А фри это немного из другой оперы. И как на мой взгляд, особо ничего не давшая. АВ происходит ничуть не реже. )) А что касается механизм Notification для вашей формы, то я согласен с вами, оно тут никчему. Вместо класической глобальной переменной, сделал бы статичное свойство в классе самой формы, и все довольны.))
-
> ухты © (17.12.18 00:20) [78]
> АВ происходит ничуть не реже. ))
счастье, когда оно происходит, а не молча портит память.
-
> сделал бы статичное свойство в классе самой формы, кто то умный давно сказал - "не плодите сущности"
> и все довольны.)) у меня нет цели сделать всех довольными... работа другая.
-
Где вы тут сущность увидели? тут как бы наоборот, инкапсуляция - привет ооп, нет гл. переменных - привет LVT и нет доп. нотификашн и т.п. - вам привет, итого все довольны.
> счастье, когда оно происходит, а не молча портит память. так а отчего тогда спасали отцы? )) в том то и дело имеем тоже и костыль
-
> Где вы тут сущность увидели? переменная в переменной это не сущность? лишняя.
она сама по себе показатель, нет смысла относится к переменной по другому только из-за того что там форма... а если нет? если указатель, простой объект, интерфейс... и что каждый по своему, как то по особому проверять? (согласен если есть объективные причины, но их нет!)
xml разбирал? мелкософтским iдомдокументом. там на отсутствующие ноды nil возвращает вместо обьекта... и никого не парит, что единственный способ проверить что вернулось, это сравнить с nil. почему с формами должно быть по другому? с чего им такая честь? и тут кстати мысль образовалась... у вас извиняюсь за личностные вопросы сколько типов ложек для супа? ну в смысле одна для борща, другая для рассольника третья для ухи и тд...? ;) т.к. если вы их не градуируете по содержимому, то советовать раздельное для каждого типа объектов сравнение попросту не имеете морального права... это батюшка называется лицемерием.
-
Вы мкня пугаете, в какой переменной? ))
-
Удалено модератором
-
> в какой переменной? )) из примера выше, например во в этой > procedure TForm1.Button2Click(Sender: TObject); > var > form: TForm; form - переменная, ты предлагаешь статику в описании типа, т.е. TForm - в итоге получается переменная в переменной, или если буквально с доступом "через переменную-тип". в общем излишние сложности, т.к. она сама показатель, ничего более не нужно.
-
> Eraser © (17.12.18 03:50) [79] > > > > ухты © (17.12.18 00:20) [78] > > > > АВ происходит ничуть не реже. )) > > счастье, когда оно происходит, а не молча портит память. >
Вот истинно 100500 да ещё и плюс. И вот очень многие "нетроешники" почему-то до сих пор этой простой истины не понимают!
-
> sniknik © (17.12.18 14:41) [85]
> > в какой переменной? )) > из примера выше, например во в этой
Поле, дельфийское поле. Вот, кстати, простой пример для формы должной жить в одном экз. http://delphimaster.net/view/2-1177420765/57Громоздко, да. Но такой уж он феньшуй. -- Regards, LVT.
-
> Но такой уж он феньшуй. https://ru.wikipedia.org/wiki/ФэншуйНет каких-либо научных доказательств того, что мистические требования фэншуй реальны; научное сообщество относит фэншуй к лженауке.что в общем то подтверждается по ссылке. http://delphimaster.net/view/2-1177420765/57procedure TForm1.Notification; begin inherited; if AComponent = FForm2 then if Operation = opRemove then FForm2 := nil; end;оппа... а с чем же это ты тогда "борешься"? под "капотом" то то же самое... все так же опираешься на обниление переменной формы. просто принцип в действии - "никогда не делать банальным и простым то, что можно сделать сложным и прекрасным..." все ясно.
-
> sniknik © (18.12.18 11:59) [88]
> procedure TForm1.Notification; > begin > inherited; > if AComponent = FForm2 then > if Operation = opRemove then > FForm2 := nil; > end; > оппа... а с чем же это ты тогда "борешься"? под "капотом" > то то же самое... все так же опираешься на обниление переменной > формы.
Поле. Его зовут полем. А опираемся на Notification.
Жаль, что ты не захотел понять.
-- Regards, LVT.
-
> Поле. Его зовут полем. это переменная, что определенная в форме, что локально в процедуре (как у меня в примере выше) что глобально. плевать. поле чисто формальное название для переменных в форме. использовать только "поля" - ограничивать себя же. что делать в моем, что выше примере? или когда нет главной формы в которой делать "поле" (или их описано несколько, в зависимости от каких то критериев выбирается на старте одно)? сложность "нотификации" возрастет многократно.
или для разных случаев у вас тоже разные варианты сравнений? ... а у вас сколько типов ложек для супов?
> Жаль, что ты не захотел понять. понимание это обоюдный процесс, когда "в одну сторону" это навязывание своего мнения оппоненту. о чем вас кстати никто не просил.
-
ооп зло
-
> sniknik © (18.12.18 14:10) [90]
> навязывание своего мнения оппоненту. о чем вас кстати никто > не просил.
Ну, извини меня, Коля.
-- Regards, LVT.
-
> Leonid Troyanovsky © (18.12.18 10:50) [87]
> Громоздко, да. Но такой уж он феньшуй.
Вот юнит, призванный упростить дело:
unit AutoNil;
interface
uses classes, Forms;
type PComponent = ^TComponent;
TMApplication = class(TApplication) private FCompVars: TList; protected procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure AutoNilVarRegister(anv: PComponent); virtual; end;
procedure NilAfterDestroy (pc: PComponent);
implementation
procedure NilAfterDestroy; begin TMApplication(Application).AutoNilVarRegister(pc); end;
procedure TMApplication.Notification; var i: Longint; begin inherited; if (Operation = opRemove) then for i := FCompVars.Count-1 downto 0 do if (PComponent(FCompVars[i])^ = AComponent) then begin PComponent(FCompVars[i])^ := nil; RemoveFreeNotification(AComponent); FCompVars.Delete(i); end; end;
procedure TMApplication.AutoNilVarRegister; begin if not Assigned(FCompVars) then FCompVars := TList.Create; FreeNotification(anv^); FCompVars.Add(anv); end;
initialization Application.Free; Application := TMApplication.Create(nil);
end.
А вот пример использования:
type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } f2, f3: TForm; public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
uses AutoNil;
type TForm2 = class(TForm) procedure DoClose(var Action: TCloseAction); override; end;
procedure TForm2.DoClose; begin inherited; Action := caFree; end;
procedure TForm1.Button1Click(Sender: TObject); begin if not Assigned(f2) then begin f2 := TForm2.CreateNew(nil); f3 := f2; NilAfterDestroy(@f2); // теперь после разрушения формы ссылка обнилится NilAfterDestroy(@f3); end; end;
procedure TForm1.Button2Click(Sender: TObject); begin if Assigned(f2) then f2.Show; end;
-- Regards, LVT.
-
> Leonid Troyanovsky © (07.01.19 15:18) [93]
Решил сэкономить на конструкторе и попал на грабли. Создавать список нужно в initialization (ну, или, дейс-но, в конструкторе). Т.е.
procedure TMApplication.AutoNilVarRegister; begin FreeNotification(anv^); FCompVars.Add(anv); end;
initialization Application.Free; Application := TMApplication.Create(nil); TMApplication(Application).FCompVars := TList.Create;
end.
-- Regards, LVT.
|