From: muler on
#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.

Thanks!

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

From: Francis Glassborow on
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.

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

From: Chris Uzdavinis on
On Dec 9, 5:04 pm, muler <mulugeta.abe...(a)gmail.com> wrote:
> #include <iostream>
>
> class My_class {
> public:
> void print() const { std::cout << "alive and well!\n"; }
>
> };

Your class has no state, so its destruction is trivial. While "double
destruction" is undefined behavior, the likely manifestation in this
case is that it works "as you would expect", even though its wrong.
Regardless of what happens to remain in memory, once an object's
destructor is invoked, it no longer exists. It is invalid to call any
non-static members or access data of that object afterwords.


> 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();

The reality is that the print function does not touch your object, as
the "this" pointer is not dereferenced, and the body of the function
you call is untouched. But it is still undefined behavior.

> }

Note: While main() exits, mc will be automatically destroyed again,
which is where more undefined behavior arises.

>
> 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"?

The destructor is somewhat like any other member, in that you can call
it yourself. It has special properties, however, in that it is
automatically invoked on variables with automatic storage. Further,
AFAIK, you cannot take the address of a destructor, or store it in a
pointer to member function, etc.

Chris


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

From: Seungbeom Kim on
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"?

The destructor call really destroys the object. Therefore, accessing
the object further causes undefined behavior. However, even though
the lifetime of the object has finished, the variable name will still
be in scope until you exit the block where the variable is defined,
because the scoping rule is static (based on the text).

In addition, adding the destructor call does not remove another
destructor call that the compiler puts automatically at the end of
the enclosing block, so there will be a double-destruction problem
in the program above. Therefore, if you want a precise control of
the lifetime, you should use something like:

My_class* p = new My_class; // allocate + construct
p->print();
delete p; // destroy + deallocate

or:

char buf[sizeof(My_class)]; // It must be aligned properly,
// to be correct actually.

My_class* p = new(buf) My_class; // construct
p->print();
p->~My_class(); // destroy

--
Seungbeom Kim

[ 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, 12:04 am, muler <mulugeta.abe...(a)gmail.com> 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;
>
> }

+1 for Francis, this is horrible code.

Now for explanation: first, when object goes out of scope, it's
destructor is called automatically. So you should almost never write
code like the above.

Second, if you should not write such code, how come it's possible to
write it? Well, one more relevant use could be:

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.

Goran.


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