TDPL: Manual invocation of destructor
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Mon Aug 9 14:17:13 PDT 2010
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
More information about the Digitalmars-d
mailing list