TDPL: Manual invocation of destructor

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Aug 9 16:40:23 PDT 2010


Steven Schveighoffer wrote:
> On Mon, 09 Aug 2010 17:17:13 -0400, Andrei Alexandrescu 
> <SeeWebsiteForEmail at erdani.org> wrote:
> 
>> Steven Schveighoffer wrote:
>>> On Mon, 09 Aug 2010 16:31:39 -0400, Andrei Alexandrescu 
>>> <SeeWebsiteForEmail at erdani.org> wrote:
>>>> Well this is my view as well and the original intent of clear(). The 
>>>> problem is, if someone defined a default constructor, they 
>>>> presumably have a nontrivial invariant to satisfy. I'm unclear on 
>>>> what's the best path to take.
>>>  Who cares about invariants when an object is destructed?
>>
>> The destructor itself.
>>
>>> First, invariants are disabled in release mode.
>>
>> I was refering to invariant in-the-large, not D's invariant keyword 
>> and associated notion.
> 
> Care to post an example?  I thought you mean D invariants.  Now, I don't 
> know what you are talking about.

class File {
     FILE * fp;
     this() { fp = fopen("/tmp/temporary"); }
     ~this() { fclose(fp); }
}

The destructor does not test fp because it assumes it was opened.

Interestingly enough, by TDPL the code above is in fact invalid already. 
TDPL mentions that an object's lifetime starts as soon as it's been 
branded, which is before default construction. As a direct consequence, 
the destructor should be able to deal with an object stamped with all 
init values for all fields - in this case a null fp.

>>> I also strongly suggest the destructor only be called once.  Having a 
>>> destructor called more than once means your destructor has to take 
>>> into account that the object may be already destructed.  This would 
>>> be helped by the same mechanism that would make sure invariants 
>>> aren't run after destruction.
>>
>> If some constructor has been called in between two calls to the 
>> destructor, there's shouldn't be any danger.
> 
> No, but let's work past that.  Here are two hard requirements for clear:
> 
> 1. it calls the target's destructor
> 2. it does not call a target's constructor.
> 
> If you can't do 2, nobody will use it.  I can just as well define a 
> reset() function on the object to do 1 without 2 (and probably do it 
> more efficiently).  I don't need any special library help for that.  The 
> user is expecting some magic stuff to happen in clear, akin to freeing 
> the object.  They are not expecting to reconstruct the object.
> 
> Here is a class which should be destructable.
> 
> class C
> {
>    private static C[int] instances;
>    private static nextid = 0;
>    private int id;
>    this()
>    {
>       id = nextid++;
>       instances[id] = this;
>    }
> 
>    ~this()
>    {
>       instances.remove(id);
>    }
> }
> 
> Can we make sure instances of this object will be destroyed?  Because if 
> you keep calling the constructor, it never dies.

In wake of the above, it looks like that's possible. The oddity will be 
that occasionally the id==0 will be removed more than one time.


Andrei


More information about the Digitalmars-d mailing list