Destructor nonsense on dlang.org
foobar
foo at bar.com
Fri May 25 05:05:01 PDT 2012
On Friday, 25 May 2012 at 11:23:40 UTC, Jacob Carlborg wrote:
> On 2012-05-25 11:02, foobar wrote:
>
>> It makes the call order deterministic like in C++.
>>
>> e.g.
>> class Foo {}
>>
>> struct A {
>> resource r;
>> ~this() { release(r); }
>> }
>>
>> struct B {
>> A* a;
>> Foo foo;
>> ~this() { delete a; } // [1]
>> }
>
> I though we were talking about classes holding structs:
>
> class B {
> A* a;
> Foo foo;
> ~this() { delete a; }
> }
>
> In this case you don't know when/if the destructor of B is
> called. It doesn't help to wrap it in a struct, you could just
> have put it directly in A. Is that correct?
>
No. see below.
>> Lets look at point [1]:
>> The "foo" instance is "managed" by the GC since the only
>> resource it
>> holds is memory. The "a" member wraps some "non-managed"
>> resource (e.g.
>> file descriptor) and in this model is still valid, thus allows
>> me to
>> deterministically dispose of it as in c++.
>
> Ok, but if B is a class?
>
>> This can be simply checked at compile-time - you can only
>> reference non
>> class instance members in the destructor, so adding a "delete
>> foo;"
>> statement at point [1] simply won't compile.
>
> If you have a pointer to a struct you don't know how it was
> created. It's possible it's been created with "new", which
> means the garbage collector needs to delete it.
let's say we add two classes:
class FooA {
A a;
}
class FooPA {
A* pa;
}
For the first case, both the class and the struct share the same
lifetime thus when an instance of FooA is GC-ed, the GC would
call A's d-tor and allow it to do what-ever (self) cleaning it
requires. This means the d-tor will always be called.
For the second case, The GC will only scan "pa" to find inner
class instances but will *not* handle the struct value itself.
In order to clean what "pa" points to, you need to explicitly
call the destructor yourself. One way to do this would be to
register a callback with the GC to get notified when an instance
of FooPA is collected and inside the callback function maintain a
reference-counter.
This also means that if you allocate a struct value on the heap
via "new" you are responsible to call delete _yourself_ and the
gc will not call it for you.
I think that loosing this small convenience is worth it - we gay
more orthogonal semantics that are easier to reason about.
More information about the Digitalmars-d
mailing list