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

> 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:
>
Depends what you mean by 'all right'. And it isn't a matter of belief. The
standard says that you have undefined behaviour. It may well be that almost
always in the context of a stateless POD that nothing bad will happen. But I
suspect that the OP's code was just to demonstrate the thing he was having a
problem with.
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.
>

Well by your argument (which has some merit) in the case of an explicit call
of a trivial dtor the object is still alive (its lifetime has not ended)


> 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.
>

On reflection, I think you are correct but I certainly would not want to
encourage code of this kind because it falls flat on its face as soon as the
dtor ceases being trivial. Just include a std::string data member and your
code is in trouble.

It would be nice if compilers warned about explicit calls of trivial dtors
(and I think they could)

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

From: A. McKenney on
On Dec 12, 5:11 am, Francis Glassborow
<francis.glassbo...(a)btinternet.com> wrote:
> Johannes Schaub (litb) wrote:
....
> > I believe both is alright:
>
> Depends what you mean by 'all right'. And it isn't a matter of belief. The
> standard says that you have undefined behaviour. It may well be that almost
> always in the context of a stateless POD that nothing bad will happen.
....
> > 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.
>
> On reflection, I think you are correct ...

Francis, it sounds like you are waffling, and if
Francis doesn't know the answer, then we are all
lost! lost! I tell you! (oh, :-) :-) :-)

I am still unclear as to what the Holy Standard says.
Is it always UB to access an object (as an object)
after the destructor call and before the placement
"new" call that constructs a new object?


For instance, assuming the source code does
not define a destructor, or the destructor is empty,
and none of the members has a non-empty destructor,
would the Standard allow the compiler to, say,
overwrite the memory with bit patterns of its choice
upon exit from the destructor?

Or to set the memory mapping registers so that
any access to the memory would trap? (And have
placement new reset the registers to allow access.)

(I don't care whether any existing implementation actually
does this, or whether it would ever make sense for it
to do so.)

It is not good for the Standard to be vague about this.
Either the user can count on the destructor only doing
what is specified by the source code, or she can't.

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