On Tuesday, 6 October 2015 at 20:44:22 UTC, ponce wrote:
On Tuesday, 6 October 2015 at 17:20:39 UTC, Jonathan M Davis wrote:

But in general, at this point, with D, if you want deterministic destruction, then you use structs. Classes are not the appropriate place for it. If they were ref-counted, then they could be, but as long as they're not, then classes are not the place to have stuff that cares about deterministic destruction. And if you're stuck with stuff in classes that do care about deterministic destruction, then you have to use the sort of solutions that C# and Java use where you don't rely on the destructor/finalizer to clean anything up except for the cases where you screw up and forget to manually call the function that does the cleanup.

Unfortunately, it is quite common to need both virtual functions and deterministic destruction. It isn't helpful to disregard the problem by saying "you should have used a struct", in many cases it's not any easier.

If you need both polymorphism and determinstic destruction, then you're just plain screwed when a GC is managing the lifetime of an object, because garbage collectors simply don't work that way. And anyone using class objects which are managed by a GC needs to understand that. To get the determinism, you need a way to control the lifetime of an object other than the GC (whether the memory for it lives on the GC heap or not). So, at this point, structs _have_ to get involved to get deterministic destruction unless you're going to do it all manually.

And that means that it's better to avoid classes if you don't actually need them, because then you can actually have deterministic destruction (on top of being able to avoid heap allocation if it's not necessary for any member variables). It also means that programs should generally avoid needing to combine polymorphism and deterministic destruction. If you need it, you need it, and you have to either get structs involved as wrappers or manually manage the lifetime of the class objects (or at least manually call a function to tell it to release whatever resources need to be released, even if the object itself isn't actually freed), but if it can reasonably be avoided, it should be avoided.

- Jonathan M Davis

Reply via email to