Prev: Templates conditional type
Next: pros and cons of returning const ref to string instead of string by value
From: muler on 9 Dec 2009 06:04 #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 9 Dec 2009 12:42 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 9 Dec 2009 18:32 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 9 Dec 2009 18:32 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 9 Dec 2009 18:32 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! ]
|
Next
|
Last
Pages: 1 2 3 Prev: Templates conditional type Next: pros and cons of returning const ref to string instead of string by value |