RAII and Deterministic Destruction
cym13 via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Tue Aug 25 18:29:28 PDT 2015
On Tuesday, 25 August 2015 at 22:35:57 UTC, Jim Hewes wrote:
> Although C++ can be ugly, one reason I keep going back to it
> rather then commit more time to reference-based languages like
> C# is because I like deterministic destruction so much. My
> question is whether D can REALLY handle this or not. I've not
> been sure about this for some time so now I'm just going to
> come out and finally ask.
>
> I know about this RAII section in the documentation:
> http://dlang.org/cpptod.html#raii
> But I don't believe that handles all cases, such as having
> classes as member variables of other classes. (Do the members
> get destructors called too?)
>
> Then there is std.typecons.Unique and std.typecons.RefCounted.
> With these, can I really get deterministic destruction for all
> cases like I would in C++?
>
> If so, it might be a good idea to emphasize this more in the
> documentation because I'd think people coming from C++ would be
> looking for this.
>
> Jim
Hi Jim. RAII in D is a common issue for people coming from C++. I
don't know everything on the subject and would be glad to be
corrected if I write a mistake but here is my share on the
subject.
There are two very different kind of objects in D and memory
management is different for each: structs and classes. I think
you mostly want to hear about classes, but I think each should be
studied nonetheless.
Structs:
=====
Why would you use structs?
- They are stack-allocated by default (but can be heap-allocated
at will)
- They are destroyed at the end of the scope, hence supporting
RAII properly
- They provide rather nice idioms for RAII [1]
- They support single-inheritance through “alias this”
- They support compile-time polymorphism through templates
- They support complex object composition through template mixins
[2]
Why wouldn't you use structs?
- You want to plug yourself on an already existing class-based
system
- You want to use interfaces
- You need runtime-polymorphism
Classes:
=====
Why would you use classes?
- They are heap-based and managed by the GC: lazy destruction
- They provide full support for inheritance and OOP (including
interfaces)
- They support compile-time polymorphism through templates
- They support complex object composition through template mixins
[2]
Why wouldn't use classes?
- They are heap-based
- They don't allow deterministic implicit destruction
How to solve these problems?
==================
Classes don't have *implicit* deterministic destruction but
nothing prevents you from calling a destructor explicitely (be it
~this or another dedicated function). This can be easily done
using scope(...) statements. If this is cumbersome,
std.typecons.Unique and std.typecons.RefCounted can be used to
provide a comportment analogous to that of modern C++. We said
that structs are scope-based, a solution is to wrap an object
into a struct and set the structs destructor to destroy the
object as well at the end of the scope. std.typecons.scoped
provides a nice wrapper arround this behaviour. The destruction
of an object doesn't mean the destruction of the objects that it
referenced. That can also be done explicitely.
A word on the GC
===========
I see a lot of C++ programmer who come to D with a single thought
in mind: “Avoid the GC at all cost, let me manage my damn
memory”. This is understandable, yet biaised. True, a GC isn't
for all applications, but it has its place. Instead of fearing
it, learning to use it well is important. One often doesn't need
deterministic destruction. Lazy destruction has its benefits. I
strongly advise not to rush trying to avoid the GC, instead
profile profile profile.
Conclusion
=======
Doing RAII is possible for structs and for classes, but it is
*really* easier with structs. D structs are really powerful and
often underestimated by newcommers who rush on the "class"
keyword. D classes aren't C++ classes. My advice would be to use
structs as much as possible, to use classes where needed relying
on the GC, and after profiling to introduce RAII behaviour into
problematic classes.
[1]
https://w0rp.com/blog/post/an-raii-constructor-by-another-name-is-just-as-sweet/
[2]
https://blog.dicebot.lv/posts/2015/08/OOP_composition_with_mixins
More information about the Digitalmars-d-learn
mailing list