Prev: Templates conditional type
Next: pros and cons of returning const ref to string instead of string by value
From: Johannes Schaub (litb) on 9 Dec 2009 20:41 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 9 Dec 2009 21:03 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 10 Dec 2009 11:32 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 11 Dec 2009 03:14 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 11 Dec 2009 17:11 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! ]
First
|
Prev
|
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 |