Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: 1 2      [все]
 Автоматическое уничтожение объектов  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1347
Реализовал (по работе) механизм, который позволяет автоматически уничтожать объекты. Избавляет от необходимости использования try..finally для удаления объектов.
Пример кода:
procedure Test;
var
  h: TSmartHolder;
  L: TList;
  ini: TIniFile;
  sl: TStrings;
begin
  L := h.CreateList(); // Создание типового объекта
  // далее используем переменную L как обычно

  h.RegObj(ini, TIniFile.Create('myfile.ini')); // Создание произвольного объекта
  // далее используем переменную ini как обычно

  sl := h.RegObj(TStringList.Create) as TStrings; // Создание произвольного объекта
end;


TSmartHolder - это простейший рекорд с единственным полем (интерфейсная ссылка).
Соответственно, все объекты будут уничтожены, как только интерфейсная ссылка будет обнулена, т.е. при выходе рекорда из области видимости.
Работает, начиная с Delphi 2007.
На мой взгляд, штука очень удобная.

Если есть интерес, я могу это оформить на своём аккаунте в гитхабе в виде отдельного модуля.
С другой стороны, не исключаю, что вариантов реализации данного велосипеда уже множество (но мне до сих пор не попадалось) :)
29 мар 21, 12:33    [22301368]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1825
Умный указатель через reference to function интереснее... там даже подсказчик кода работает и синтаксис использования не меняется, кроме объявления...
29 мар 21, 13:59    [22301415]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1347
X-Cite
Умный указатель через reference to function интереснее... там даже подсказчик кода работает и синтаксис использования не меняется, кроме объявления...


Где посмотреть на это?
29 мар 21, 14:03    [22301420]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12789
DmSer
TSmartHolder - это простейший рекорд с единственным полем (интерфейсная ссылка).
Тогда ты ее постоянно перезаписываешь. Или там у тебя какой-то IInterfacedList?
DmSer
На мой взгляд, штука очень удобная.
Если изменить требование D2007 на D2009, то RegObj можно объявить дженерик методом и уйти от каста
function RegObj<T: class>(const AVal: T): T;

DmSer
На мой взгляд, штука очень удобная.
Иногда последовательность уничтожения объектов важна.
29 мар 21, 14:07    [22301424]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
rgreat
Member

Откуда:
Сообщений: 6653
ИМХО это не красиво и не очень удобно.

Не надо связываться с интерфейсами, где это явно не требуется.

В конце концов если сильно хочется - используй рекорды. Благо там теперь и конструктор с деструктором есть.
29 мар 21, 14:15    [22301430]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1347
Тогда ты ее постоянно перезаписываешь. Или там у тебя какой-то IInterfacedList?


Там объект, который хранит список зарегистрированных объектов в TList. Объект реализует интерфейс. В рекорде хранится интерфейсная ссылка на этот объект.

Если изменить требование D2007 на D2009, то RegObj можно объявить дженерик методом и уйти от каста


Можно, как вариант.

Иногда последовательность уничтожения объектов важна


Разные ситуации бывают, конечно.
29 мар 21, 14:20    [22301432]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1347
rgreat
ИМХО это не красиво и не очень удобно.

Не надо связываться с интерфейсами, где это явно не требуется.

В конце концов если сильно хочется - используй рекорды. Благо там теперь и конструктор с деструктором есть.


В коде нет явной работы с интерфейсами (см. пример в начале). Всё спрятано в методы рекорда. Интерфейсная ссылка объявлена как private.
29 мар 21, 14:23    [22301438]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1825
  ISmartPointer<T: class> = reference to function: T;

  TSmartPointer<T: class> = class(TInterfacedObject, ISmartPointer<T>)
  strict private
    FObject: T;
    function Invoke: T; inline;
  public
    constructor Create(const aObject: T);
    destructor Destroy; override;
  end;


{ TSmartPointer<T> }

function TSmartPointer<T>.Invoke: T;
begin
  Exit(FObject);
end;

constructor TSmartPointer<T>.Create(const aObject: T);
begin
  FObject := aObject;
end;

destructor TSmartPointer<T>.Destroy;
begin
  FreeAndNil(FObject);
  inherited Destroy();
end;

procedure TForm2.Button1Click(Sender: TObject);
var
  x: ISmartPointer<TForm2>;
begin
  x := TSmartPointer<TForm2>.Create(TForm2.Create(nil));
  x.Caption := '123';
  x.ShowModal();
end;


В последних версиях сломали правда CodeInsight...
29 мар 21, 14:27    [22301442]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1347
Использование RegObj выглядит не очень красиво. К сожалению. Тут ничего не поделаешь.
Но такой код смотрится вполне прилично:

var L := h.CreateStringList();


можно так:
var L := TStringList.Create();
h.RegObj(L);


У меня в коде есть классы, которые я чаще всего использую (назовём их "типовые классы"). Для них сделал функции создания объекта (CreateStringList, CreateList и т.п.). Иногда добавляю новые функции по мере необходимости. Но это свой фирменный велосипед :)
29 мар 21, 14:31    [22301445]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
alekcvp
Member

Откуда:
Сообщений: 2792
X-Cite,

destructor TSmartPointer<T>.Destroy;
begin
  FreeAndNil(FObject);
  inherited Destroy();
end;

Зачем?.. Почему не Free?

Ну и каждое обращение к переменной - вызов функции, ну такое себе. Хотя надо смотреть как компилятор вызов заинлайнит.

Сообщение было отредактировано: 29 мар 21, 14:26
29 мар 21, 14:31    [22301446]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1825
alekcvp,

Да все равно... Можно и Free
Ну это уже проблемы компилятора, если он не сможет заинлайнить))) За сомнительное удобство, не из коробки, надо платить...
29 мар 21, 14:41    [22301456]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 5101
alekcvp
Хотя надо смотреть как компилятор вызов заинлайнит.

Это же интерфейс, откуда там инлайну взяться. Однако, прикольное колдунство :)

Сообщение было отредактировано: 29 мар 21, 14:38
29 мар 21, 14:45    [22301459]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1347
var
x: ISmartPointer<TForm2>;
begin
x := TSmartPointer<TForm2>.Create(TForm2.Create(nil));


Не заметил особого преимущества по сравнению с

var
  x: TForm2;
  h: TSmartHolder;
begin
  x := h.RegObj(TForm2.Create(nil)) as TForm2;


А пытаться понять как работает ISmartPointer - ещё сложнее, чем разобраться с фильмом Довод :)
29 мар 21, 15:07    [22301469]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 5101
DmSer
Не заметил особого преимущества

Если правильно помню, эту запись:
x := TSmartPointer<TForm2>.Create(TForm2.Create(nil));

можно сократить до:
x := TSmartPointer.Create(TForm2.Create(nil));

или вообще создание смартпоинтера завернуть в функцию, например:
x := Auto(TForm2.Create(nil));
29 мар 21, 15:17    [22301473]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12789
Kazantsev Alexey
можно сократить до:
Нельзя.
1. TSmartPointer и TSmartPointer<T> - это разные типы.
2. Можно было бы писать
x := TSmartPointer<>.Create(TForm2.Create(nil));
но это вам не джава и автовывод типов сюда не завезли
Kazantsev Alexey
или вообще создание смартпоинтера завернуть в функцию,
Нельзя. Дженерик-функций не бывает
29 мар 21, 15:28    [22301484]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 5101
_Vasilisk_
Нельзя.
1. TSmartPointer и TSmartPointer<T> - это разные типы.

Верно, только не специализированных дженериков не бывает.

_Vasilisk_
но это вам не джава и автовывод типов сюда не завезли

Да, это я с выводом типов для дженериковых методов спутал.

_Vasilisk_
Нельзя. Дженерик-функций не бывает

А это я с FPC спутал, там они есть :)
29 мар 21, 15:37    [22301493]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6314
DmSer,

в любом случае если у тебя появляется AS, значит код уже сразу выглядит аналогично тому как звучит
нельзя использовать хаки везде подряд, карма портится
29 мар 21, 15:44    [22301501]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6314
_Vasilisk_
Kazantsev Alexey
можно сократить до:
Нельзя.
1. TSmartPointer и TSmartPointer<T> - это разные типы.
2. Можно было бы писать
x := TSmartPointer<>.Create(TForm2.Create(nil));
но это вам не джава и автовывод типов сюда не завезли
Kazantsev Alexey
или вообще создание смартпоинтера завернуть в функцию,
Нельзя. Дженерик-функций не бывает
как вариант можно хелпером к TObject, мало уже кто функции пишет чистые
29 мар 21, 15:46    [22301504]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1347
kealon(Ruslan)
DmSer,

в любом случае если у тебя появляется AS, значит код уже сразу выглядит аналогично тому как звучит
нельзя использовать хаки везде подряд, карма портится


Мы пока на D2007 работаем. Деваться некуда :))
29 мар 21, 15:51    [22301507]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1825
_Vasilisk_
Нельзя. Дженерик-функций не бывает


Бывают)
  TStatic = class
  public
    class function Test<T: class>(const aObj: T): T; static;
  end;

Например так :)

Сообщение было отредактировано: 29 мар 21, 16:32
29 мар 21, 16:39    [22301534]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1825
А вообще в Spring 4D реализованы smart pointers на вкус и цвет..

  {$REGION 'Shared smart pointer'}

  IShared<T> = reference to function: T;

  {$REGION 'Weak smart pointer'}

  IWeakReference<T> = interface
29 мар 21, 16:44    [22301536]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 15181
X-Cite
Да все равно... Можно и Free


а если останется ссылка и ты будешь проверять и обращаться? будет AV
думаю, FreeAndNil - правильный всегда вариант
29 мар 21, 18:34    [22301627]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
alekcvp
Member

Откуда:
Сообщений: 2792
X11
X-Cite
Да все равно... Можно и Free

а если останется ссылка и ты будешь проверять и обращаться? будет AV
думаю, FreeAndNil - правильный всегда вариант

Какая ссылка, если речь идёт о деструкторе?.. Если у тебя после этого останется ссылка, к которой ты будешь обращаться, то ты ССЗБ.
29 мар 21, 19:27    [22301650]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 15181
после Free остается ссылка
не зря ведь придумали FreeAndNil

o := TObject.Create;
o.Free;

if Assigned(o) then o.Width := 10;


По идее Assigned(o) вернет True

Сообщение было отредактировано: 29 мар 21, 19:40
29 мар 21, 19:46    [22301663]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
rgreat
Member

Откуда:
Сообщений: 6653
X11
после Free остается ссылка
не зря ведь придумали FreeAndNil

o := TObject.Create;
o.Free;

if Assigned(o) then o.Width := 10;


По идее Assigned(o) вернет True

А не надо так делать.

Вообще с Assigned надо быть очень аккуратным и точно знать как работает то что туда передаешь.
Ибо если не уверен на 100% что в o может быть либо живой объект либо nil то Assigned применять вообще нельзя.

Сообщение было отредактировано: 29 мар 21, 20:02
29 мар 21, 20:06    [22301671]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6314
rgreat,

зачем мне Assigned если я буду уверен, что там всё хорошо?
29 мар 21, 20:19    [22301675]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
rgreat
Member

Откуда:
Сообщений: 6653
kealon(Ruslan)
rgreat,

зачем мне Assigned если я буду уверен, что там всё хорошо?

"Хорошо" - это 100% уверенность в том что по указателю не может быть мусора.
Только либо живой объект либо nil.

Если 100% уверенности в таком нет, то и Assign использовать никак нельзя.

Разве что так:
if Assigned(X) then begin
  try 
    X.DoSomething;
  except
  end;
end;

Но тут и assign-то нужен только для того что бы тормозило меньше.

Сообщение было отредактировано: 29 мар 21, 20:37
29 мар 21, 20:42    [22301682]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
alekcvp
Member

Откуда:
Сообщений: 2792
X11
после Free остается ссылка

Тебе не всё равно что там останется, если после вызова деструктора ссылка на сам интерфейс будет невалидной?..
29 мар 21, 23:04    [22301733]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
JayDi
Member

Откуда: Сызрань, Россия
Сообщений: 4173
В методах такая фишка с автоуничтожением бесполезна, как по мне -- там у программиста полный контроль. А вот в сложных схемах, где создание и уничтожение разделены во времени и месту -- может пригодиться.

Например, я аналог такого объекта использовал для сборки и корректного уничтожения созданных ресурсов при завершении/закрытии приложения, когда оно может быть завершено в любой момент, а проверять вручную каждый ресурс накладно/муторно.
29 мар 21, 23:48    [22301754]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
JayDi
Member

Откуда: Сызрань, Россия
Сообщений: 4173
А вообще, есть одна задача, где автоуничтожение могло быть полезно (если натянуть сову на глобус): если у нас есть список объектов, но при этом часть из них должно быть уничтожено (к примеру, мы туда копии/временные значения помещаем).

Иногда встречалось подобное, решалось созданием отдельного списка для хранения временных объектов, который потом и уничтожался.

Пример:

var
  refs: TList<TObject>;
begin
  refs: TList<TObject>.Create;

  // основной код, заполняет список реальными объектами, которые в другом месте хранятся
  refs.Add(realObject);
  
  // дополнительный код, который добавляет временные значения, созданные тут же
  refs.Add(realObject.CopyAndModify());

  // тогда при завершении мы должны уничтожить сам список и все копии, которые в нем есть, но не оригиналы
  FreeAndNil(refs);
end;
30 мар 21, 00:02    [22301757]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
softwarer
Member

Откуда: 127.0.0.1
Сообщений: 65408
Блог
DmSer
TSmartHolder - это простейший рекорд с единственным полем (интерфейсная ссылка).

Ну и зачем тебе трёхколёсный цирковой велосипед?

16620568
30 мар 21, 00:04    [22301758]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
softwarer
Member

Откуда: 127.0.0.1
Сообщений: 65408
Блог
JayDi
В методах такая фишка с автоуничтожением бесполезна, как по мне

Наоборот. Она полезна примерно в той же степени, что и исключения.
30 мар 21, 00:06    [22301760]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
softwarer
Member

Откуда: 127.0.0.1
Сообщений: 65408
Блог
rgreat
"Хорошо" - это 100% уверенность в том что по указателю не может быть мусора. Только либо живой объект либо nil.

Ну, если кто-то программирует без подобной уверенности, он... рисковый чувак с тягой к гомосексуальным контактам, назовём так.
30 мар 21, 00:07    [22301761]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
ma1tus
Member

Откуда:
Сообщений: 778
встречалась минимум пара реализаций (без пруфов), но... "запас карман не тяготит"(c) -
DmSer
могу это оформить на своём аккаунте в гитхабе в виде отдельного модуля
do it, please )

Сообщение было отредактировано: 30 мар 21, 05:56
30 мар 21, 05:58    [22301787]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 15181
rgreat
X11
после Free остается ссылка
не зря ведь придумали FreeAndNil

o := TObject.Create;
o.Free;

if Assigned(o) then o.Width := 10;



По идее Assigned(o) вернет True

А не надо так делать.

Вообще с Assigned надо быть очень аккуратным и точно знать как работает то что туда передаешь.
Ибо если не уверен на 100% что в o может быть либо живой объект либо nil то Assigned применять вообще нельзя.


а как жеж тогда проверить существование объекта?
30 мар 21, 08:24    [22301802]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 15181
alekcvp
X11
после Free остается ссылка

Тебе не всё равно что там останется, если после вызова деструктора ссылка на сам интерфейс будет невалидной?..


в том-то и дело, что при повторном использовании не все равно - надо знать и быть уверенным

Сообщение было отредактировано: 30 мар 21, 08:18
30 мар 21, 08:25    [22301803]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 27064
Такой код мне кажется более читабельным:

var
  List: TStringList;
begin
  List := Auto(TStringList.Create).Instance;
  // Do stuff with List...
  // No need to free anything.
  // Will automatically free contained object when interface goes out of scope. ie. at end of procedure/method.
  // Copes with exceptions - no need for try finally
end;


+
nterface
 
type
 
  IcaAutoFree = interface
  ['{FEC11200-4C4E-49D7-9F9F-C7178A687DA4}']
    // Property methods
    function GetInstance: Pointer;
    // Properties
    property Instance: Pointer read GetInstance;
  end;
 
  TcaAutoFree = class(TInterfacedObject, IcaAutoFree)
  private
    // Private fields
    FInstance: TObject;
    // Property methods
    function GetInstance: Pointer;
  public
    constructor Create(AInstance: TObject);
    destructor Destroy; override;
  end;
 
function Auto(AInstance: TObject): IcaAutoFree;
 
implementation
 
constructor TcaAutoFree.Create(AInstance: TObject);
begin
  inherited Create;
  FInstance := AInstance;
end;
 
destructor TcaAutoFree.Destroy;
begin
  FInstance.Free;
  inherited;
end;
 
  // Property methods
 
function TcaAutoFree.GetInstance: Pointer;
begin
  Result := FInstance;
end;
 
function Auto(AInstance: TObject): IcaAutoFree;
begin
  Result := TcaAutoFree.Create(AInstance);
end;


Src: https://forum.lazarus.freepascal.org/index.php/topic,37524.msg252351.html#msg252351
30 мар 21, 09:22    [22301824]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
Dmitry Arefiev
Member

Откуда:
Сообщений: 9961
И что бенчмарк показывает ?
30 мар 21, 09:25    [22301825]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6314
wadman,

вот только контроль типов исчезает
30 мар 21, 09:32    [22301828]     Ответить | Цитировать Сообщить модератору
 Re: Автоматическое уничтожение объектов  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 682
Тоже добавлю свой вариант, банальный. Сахара не прикручивал, т.к. особо и не понадобилось пока

  //   var ptr: IAutoPtr<TTestClass>;
  //   ptr := TAutoPtr<TTestClass>.Create(TTestClass.Create);
  //   ptr.Obj.SomeMethod ...
  IAutoPtr<T: class> = interface
    function GetObject: T;
    property Obj: T read GetObject;
  end;

  TAutoPtr<T: class> = class(TInterfacedObject, IAutoPtr<T>)
  strict private
    FObj: T;
  public
    constructor Create(Obj: T);
    destructor Destroy; override;
    function GetObject: T;
  end;

{$REGION 'TAutoPtr<T>'}

constructor TAutoPtr<T>.Create(Obj: T);
begin
  inherited Create;
  FObj := Obj;
end;

destructor TAutoPtr<T>.Destroy;
begin
  FreeAndNil(FObj);
  inherited;
end;

function TAutoPtr<T>.GetObject: T;
begin
  Result := FObj;
end;

{$ENDREGION}
30 мар 21, 10:42    [22301868]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: 1 2      [все]
Все форумы / Delphi Ответить