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