From: Johannes Schaub (litb) on
Francis Glassborow wrote:

> muler wrote:
>> #include <iostream>
>>
>> class My_class {
>> public:
>> void print() const { std::cout << "alive and well!\n"; }
>> };
>>
>> int main(int argc, char* argv[])
>> {
>> My_class mc;
>> // ..
>> mc.~My_class();
>>
>> // mc is destroyed above, right? how come it come be used?
>> mc.print();
>>
>> return 0;
>> }
>>
>> Or, is the destructor just like any other member function except that
>> it would give the object of class a chance to "clean" itself before it
>> is de-allocated by the run-time (when object goes out of scope) or
>> when we call the "operator delete"?
>>
>> Please elaborate.
>
> Wow!! You have been lucky, doubly so. First mc.print() has undefined
> behaviour yet you did not get bitten by it. Then you destroyed a local
> variable and did not replace it before the automatic destructor call
> happened when it went out of scope.
>
> More to the point, why should a compiler waste time checking that the
> programmer does not try to use an object after he has manually destroyed
> it. Such manual destruction serves no purpose unless you were going to
> replace it.
>

I believe both is alright: This is a POD with a trivial destructor, and the
manual destructor call does not end the lifetime of the object then (see
3.8/1). And the rule (3.8/8) that says you have to construct an object of
the original type when an implicit dtor call happens does in my opinion even
not make behavior undefined when lifetime of the object ended by a manual
dtor call - because even if lifetime ended, there *still* exists an object
of the original type (the object was created by the definition, and it was
not yet destroyed by leaving its block) - it's just not alive.

This latter thing sounds odd though, and if my understanding of lifetime and
object existance is correct, then this is a defect i think. Since it should
state that an *alive* object of the original type should occupy the storage
location. But this does not affect that example anyway, which i believe is
alright.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Francis Glassborow on
Goran wrote:
> TYPE* p = new TYPE; // Object allocated on the heap.
> // work work work
> p->~TYPE(); // destroy object, but __preserve heap storage__
> p = new (p) TYPE; // construct another object in same place
>
> Why could this be relevant? Only if performance profiling pinpointed a
> call to new as expensive. (But! That's very improbable anyhow, and
> even less if new object is constructed immediately after ~TYPE,
> because heap allocator, if it's any smart, will quickly find new free
> heap slot - the one that was just "delete"-d).
>
> When object is on stack, or embedded in (a member of) another object,
> I know of no practical reason to call destructor explicitly.

Because you want to use placement new to reset the object to its default
state? Yes, unusual but not inconceivable. That is why the Standard
explicitly allows such as long as the destroyed object is replaced by an
object of the same type before the automatic dtor call.



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Frank Birbacher on
Hi!

Francis Glassborow schrieb:
> Because you want to use placement new to reset the object to its default
> state? Yes, unusual but not inconceivable. That is why the Standard
> explicitly allows such as long as the destroyed object is replaced by an
> object of the same type before the automatic dtor call.


Trouble is if you cannot construct a new object due to errors. If an
exception is raised from within the constructor you have to catch it
before leaving the scope, and then retry constructing an instance.
Because leaving the scope will always call the destructor again, and you
better have an object in place then or all bets are off.

Frank

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Goran on
On Dec 10, 3:03 pm, Francis Glassborow
<francis.glassbo...(a)btinternet.com> wrote:
> > When object is on stack, or embedded in (a member of) another object,
> > I know of no practical reason to call destructor explicitly.
>
> Because you want to use placement new to reset the object to its default
> state? Yes, unusual but not inconceivable. That is why the Standard
> explicitly allows such as long as the destroyed object is replaced by an
> object of the same type before the automatic dtor call.

If that's the case, I'd rather do:

{
TYPE object1(params);
// workworkwork
}
{
TYPE object2(params);
// workworkwork
}

If compiler can reuse object1's stack for object2, I get all for free
without abominations. If not, and if stack space is a problem, I'd
just go on the heap.

Note that using blocks is also more exception safe, too, e.g.:

TYPE object(params);
// workworkwork
object.~TYPE();
try
{
pObject = new (&object) TYPE(params)
}
catch(blah) {}
object.crash_here();

If there are other references to said object, and it has to go to
initial state I'd prefer e.g. a "clear" method. In fact, if there are
said references, situation is even worse WRT exception safety: if ctor
throws, object isn't constructed anymore (a MAJOR nono), and yet,
there are references to it. And if base class, or some member ctor
throws, in usual implementations, virtual table stays broken, which is
__utter__ disaster.

So to me, your use clearly falls under "just because you can, doesn't
mean you should".

Goran.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Francis Glassborow on
Frank Birbacher wrote:

> Hi!
>
> Francis Glassborow schrieb:
>
>> Because you want to use placement new to reset the object to its default
>> state? Yes, unusual but not inconceivable. That is why the Standard
>> explicitly allows such as long as the destroyed object is replaced by an
>> object of the same type before the automatic dtor call.
>>
>
>
> Trouble is if you cannot construct a new object due to errors. If an
> exception is raised from within the constructor you have to catch it before
> leaving the scope, and then retry constructing an instance. Because leaving
> the scope will always call the destructor again, and you better have an
> object in place then or all bets are off.
>
> So do not use a throwing ctor :) IOWs if the ctor can throw you cannot use
that mechanism but that does not invalidate the mechanism itself, only some
uses of it.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]