On 2011-09-12 11:37:20 +0000, "Steven Schveighoffer"
<[email protected]> said:
On Mon, 12 Sep 2011 07:12:19 -0400, Michel Fortin
<[email protected]> wrote:
On 2011-09-11 10:23:21 +0000, "Marco Leise" <[email protected]> said:
Enough sarcasm. If I recall, Andrei liked the name 'clear' and was
unsympathetic to the arguments that it'd be confusing. 'clear' is
explained in TDPL and Andrei doesn't like to break his book, so we
might be stuck with that mess for while. But I think it's clear by now
that that 'clear' is confusing and dangerous: it will work with
certain types and completely blow up with others depending on
implementation details of the type (calling the destructor twice, it's
insane!). And the name just make it sounds like it's something pretty
normal to do, which is probably the worse part of it. Actually no, the
worse part is probably that it's inside module 'object', the only
module imported by default everywhere, so you can't even escape the
confusion by not importing its module. :-(
While I share your sentiment that clear is too useful a term to be
relegated to only be "call the destructor" (in fact, I use clear as a
member function in my dcollections library, which probably adds to the
confusion), I still think that the function should work. What types
does it "blow up" on? What types does it call the destructor twice?
I'd like to fix these.
It can "blow up" when the destructor is called twice and the destructor
doesn't expect this. The destructor will be called twice when you use
it on a struct variable on the stack. You'll probably say it shouldn't
be used on stack variables, but if something work, especially if it
looks pretty and appropriate like 'clear' does, people will use it
anyway and write programs that'll break later when the implementation
behind an API changes. Remember that this problem couldn't happen with
'delete'…
'clear' conflates two things: restoring the object to its pristine
state, and releasing resources. It does succeed at releasing resources,
but only because it reaches half of the former goal. I think it'd be
much wiser to have two different functions for these two concepts.
I think 'delete' is the one that should be tasked with releasing
resources. Just change 'delete' so it calls the destructor, wipes all
the bits, but keep the memory block alive so it gets collected later
by the GC, keeping things memory-safe. There's absolutely no point in
reinstating the original 'init' bits if what you want is to destroy the
object. 'delete' only works with memory allocated on the heap, not
stack variables, not memory allocated elsewhere, so it's easy to make
sure destructors don't get called twice because that's a bit in the
GC's block flags.
Then you can make 'clear' a function that actually does what people
expects it to do: restore the object to its pristine state: calling the
destructor, reinstating the 'init' bits, then calling constructor again
if necessary. It could be safe to call on stack variables, and it could
fail if the default constructor is disabled (like in NotNull!T).
--
Michel Fortin
[email protected]
http://michelf.com/