I find that often I just need my local variables to be freed, without reference counting. And ideally I would like not to add any more code than with arrays.
Here is a record to handle that for classes having a constructor without parameters:
unit Local; {$modeswitch advancedRecords} interface type { LocalClass } generic LocalClass<T: class> = record private type TSelf = specialize LocalClass<T>; var FInstance: T; class operator Initialize(var ASelf: TSelf); inline; class operator Finalize(var ASelf: TSelf); inline; function GetInstance: T; inline; procedure SetInstance(const AInstance: T); inline; public function Give: T; property _: T read GetInstance write SetInstance; end; implementation class operator LocalClass.Initialize(var ASelf: TSelf); begin ASelf.FInstance:= nil; end; class operator LocalClass.Finalize(var ASelf: TSelf); begin ASelf.FInstance.Free; end; procedure LocalClass.SetInstance(const AInstance: T); begin if Assigned(FInstance) then FInstance.Free; FInstance := AInstance; end; function LocalClass.GetInstance: T; begin if FInstance = nil then FInstance := T.Create; result := FInstance; end; function LocalClass.Give: T; begin result := FInstance; FInstance := nil; end; end.
It can be used like that:
uses Classes, Local; type StringList = specialize LocalClass<TStringList>; var list: StringList; taken: TStringList; begin list._.Add('Hello'); list._.Add('Alice'); list._.Sort; WriteLn(list._.CommaText); taken := list.Give; // display 0 because list is reset writeln(list._.Count); taken.Add('Bob'); // display Alice,Bob,Hello WriteLn(taken.CommaText); taken.Free; // need to free it list._.Add('Alice'); // clear the list list._ := nil; list._.Add('Mirror'); // display Mirror WriteLn(list._.CommaText); end.
You did not come up with that. I did. Three-four years ago. Also Marco Cantu and Barry Kelly.
But the principle is about the same. Just do not claim it.
The proof is on this forum btw. With multiple ( I forgot AVK and HNB, sorry) implementations that are all correct.
So revisisted is really a well chosen wording...
See earlier discussion here: https://forum.lazarus.freepascal.org/index.php/topic,46306.0.html
I have adapted Aserge's implementation for my own use, but it is not really in a form for others to consume.
However, for my own usage is has been working very well. I instantiate classes using the mechanism wherever I need, pass around those instances as needed, and I don't have to working around freeing them, as that is handled automatically. The destructors run at the expected times, never too early, never to late.
I was wondering if there is any thought or planning being considered to offer generalized smart pointer implementations in the FCL in some upcoming release of Free Pascal.
Right now I'm asking because of this thread: https://forum.lazarus.freepascal.org/index.php/topic,62148.0.html where OP zelda16bit asked for an example of smart pointer use in Free Pascal.
Also the defer mechanism I came up with that also uses advanced records.
https://forum.lazarus.freepascal.org/index.php/topic,55154.0.html
https://github.com/bogen85/fpc-defer
No big deal. Actually sorry I got a bit angry. Wrong Fish on the plate...
You can create a class that handles a list of objects and add itself to that list and free it in that same class, so that later the classes that inherit from it do not have to be freed since the list of the parent class is freeing it. .
This is basically the dynamic C++ introduced with C++11 with their shared vs unique pointer. Shared pointer have reference counter to be used from multiple locations while unique pointer have always the lifetime of the owner (unique pointer as class member gets automatically destroyed when the class gets destroyed, as variable when the variable goes out of scope)I find that often I just need my local variables to be freed, without reference counting. And ideally I would like not to add any more code than with arrays.
Here is a record to handle that for classes having a constructor without parameters:
Agreed (and I replied here rather than the 3+ month old topic).
There are a lot of things I don't use smart pointers for and instead use existing managed types like dynamic arrays that already do automatic cleanup.
Or advanced records rather than classes (which is what smart pointers leverage)
Also the defer mechanism I came up with that also uses advanced records.
https://forum.lazarus.freepascal.org/index.php/topic,55154.0.html
https://github.com/bogen85/fpc-defer
Which the idea was based on yours and other's examples.It did not seem to me that you were claiming that.
Once again, I apologize.
It was not my intent to claim it as my own.
I apologize for it coming across that way. I will try to be more careful in the future, so as to not make this mistake again.
This is basically the dynamic C++ introduced with C++11 with their shared vs unique pointer. Shared pointer have reference counter to be used from multiple locations while unique pointer have always the lifetime of the owner (unique pointer as class member gets automatically destroyed when the class gets destroyed, as variable when the variable goes out of scope)Indeed, that's not new conceptually. I suppose that generics at last allow to do that in Pascal and that's good news. :)
What's also quite useful would be scope managed stack objects, e.g. a file stream that automatically gets closed when the variable goes out of scopeIndeed. I am not sure though that there would be a generic way to do that, unless there is a common name for a method on a record/object to call in order to dispose of it.
Indeed. I am not sure though that there would be a generic way to do that, unless there is a common name for a method on a record/object to call in order to dispose of it.Back then I built this using generic finalizers, so for handling classes you would use the class finalizers which would call free on that class. For objects there was the object finalizers which calls final and for all other types there was the finalize finalizers that would call finalize.