TDPL: Manual invocation of destructor

Lutger lutger.blijdestijn at gmail.com
Mon Aug 9 14:44:12 PDT 2010


Andrei Alexandrescu wrote:

> Steven Schveighoffer wrote:
>> On Mon, 09 Aug 2010 16:31:39 -0400, Andrei Alexandrescu
>> <SeeWebsiteForEmail at erdani.org> wrote:
>> 
>>> Steven Schveighoffer wrote:
>>>> On Mon, 09 Aug 2010 15:46:27 -0400, Andrei Alexandrescu
>>>> <SeeWebsiteForEmail at erdani.org> wrote:
>>>>
>>>>> Lutger wrote:
>>>>>> Steven Schveighoffer wrote:
>>>>>>
>>>>>>> On Mon, 09 Aug 2010 08:28:38 -0400, Andrej Mitrovic
>>>>>>> <andrej.mitrovich at gmail.com> wrote:
>>>>>>>
>>>>>>>> It's rather perplexing, isn't it? It states in TDPL:
>>>>>>>>
>>>>>>>> "After you invoke clear, the object is still alive and well, but its
>>>>>>>> destructor has been called and the object is now carrying its
>>>>>>>> default-constructed stated. During the next garbage collection, the
>>>>>>>> destructor is called again, because the garbage collector has no
>>>>>>>> idea in
>>>>>>>> what state you have left the object."
>>>>>>> This seems totally wrong, what if an object has no default
>>>>>>> constructor?
>>>>>>> The spec used to say (maybe it still does) that a destructor is
>>>>>>> guaranteed
>>>>>>> to only ever be called once.
>>>>>>  The spec still does, it is not updated since it describes delete,
>>>>>> not clear.  If you omit the default constructor, no constructor
>>>>>> will be called. Also not for the base classes even if they have a
>>>>>> default constructor. This looks like a bug.
>>>>>
>>>>> Yes, not calling the constructors of base classes is an
>>>>> implementation bug. If a class does not define any constructor at
>>>>> all, it has a de facto default constructor. If a class does define
>>>>> some constructor but not a parameterless one, it is a bug in the
>>>>> implementation if clear() compiles.
>>>>  How can this be decided at compile time?
>>>>  basic counter-example:
>>>>  class C
>>>> {
>>>>    this(int x) {}
>>>> }
>>>>  // how do you statically disable this?
>>>> void foo(Object o)
>>>> {
>>>>   clear(o);
>>>> }
>>>>  void foo(C c)
>>>> {
>>>>    auto c = new C(1);
>>>>    foo(c);
>>>> }
>>>
>>> Sorry, I got things mixed.
>>>
>>>> I always thought clear would simply overwrite the object with it's
>>>> default data as defined in the TypeInfo (i.e. before a constructor is
>>>> normally called).  Calling the constructor is absolutely wrong.  We
>>>> don't want to reset the object, we want to free it's resources.
>>>> Re-constructing it may reallocate resources *THAT WE JUST ASKED TO BE
>>>> DESTROYED MANUALLY*.  To say clear as defined is a replacement for
>>>> delete is complete fantasy.
>>>
>>> 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.
> 
>> 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.
> 
> 
> Andrei

Are there any problems with said 'some constructor' being a user-defined 
function, either through convention or interface? If a class needs to define a 
destructor, *and* requires a default constructor, I don't think it is too much 
to ask for a third 'reinitialize' function (or some other solution.)

Take a look at what IDisposable requires for comparison:

http://msdn.microsoft.com/en-us/library/system.idisposable.aspx


More information about the Digitalmars-d mailing list