Andrei Alexandrescu wrote: > Steven Schveighoffer wrote: >> On Mon, 09 Aug 2010 16:31:39 -0400, Andrei Alexandrescu >> <[email protected]> wrote: >> >>> Steven Schveighoffer wrote: >>>> On Mon, 09 Aug 2010 15:46:27 -0400, Andrei Alexandrescu >>>> <[email protected]> wrote: >>>> >>>>> Lutger wrote: >>>>>> Steven Schveighoffer wrote: >>>>>> >>>>>>> On Mon, 09 Aug 2010 08:28:38 -0400, Andrej Mitrovic >>>>>>> <[email protected]> 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
