RAII and Deterministic Destruction

ZombineDev via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Aug 25 18:55:37 PDT 2015


On Wednesday, 26 August 2015 at 01:18:43 UTC, ZombineDev wrote:
> On Wednesday, 26 August 2015 at 01:09:15 UTC, ZombineDev wrote:
>> 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
>>
>> Structs in D behave like in C++ - they are created on the 
>> stack (unless you use new or malloc), passed by value and are 
>> automatically destroyed at the end of the scope. All their 
>> members are destroyed recursively after the user defined 
>> destructor is called.
>>
>> Just try it out in a toy program and see if it works as you 
>> expect.
>
> Classes on the other hand are reference types and are created 
> on the garbage-collected heap by default (though you can do 
> your own memory management). Similarly, structs created by new 
> are also allocated on the GC heap. During collections the GC 
> will call destructors, but it is not guaranteed and you should 
> not rely on it. For example (depending on your GC usage and 
> configuration) only a single collection may occur at the end of 
> the program.

Generally a very tutorial and reference is Ali's book [1], which 
is listed under Books and Articles in the sidebar of dlang.org.
You should check the chapters Constructor and Other Special 
Functions [2] and Memory Management [3] (even though it covers 
mostly the GC).

If you wish to avoid the GC, you can annotate your functions with 
the @nogc attribute [4] which enforces at compile-time that the 
annotated function won't use the GC. It is transitive which means 
that if you annotate your main() function with it, you shouldn't 
be allowed to use anything that allocates memory from the GC in 
your whole program.
Since this feature was added there is an ongoing effort to 
minimize GC usage in the standard library, but there's still 
stuff that require it. That said the recommended approach is to 
build your data processing on ranges [5] (see the linked article 
by Andrei Alexandrescu) because it allows you to encapsulate 
memory usage more strategically. This is enabled by the lazy 
nature of ranges - they process data only when needed and so they 
don't need to allocate memory.

Probably the best introduction to this technique is Walter 
Bright's keynote at DConf 2015 [6]: 
https://www.youtube.com/watch?v=znjesAXEEqw

Be sure to check the DConf website as there's lots of great 
content from 2013 [7], 2014 [8] and 2015 [9].

[1]: http://ddili.org/ders/d.en/index.html
[2]: http://ddili.org/ders/d.en/special_functions.html
[3]: http://ddili.org/ders/d.en/memory.html
[4]: http://dlang.org/attribute.html#nogc
[5]: http://dlang.org/phobos/std_range.html
[6]: https://www.youtube.com/watch?v=znjesAXEEqw
[7]: http://dconf.org/2013/
[8]: http://dconf.org/2014/
[9]: http://dconf.org/2015/


More information about the Digitalmars-d-learn mailing list