following on this: is destructor called when delegating constructor throws?
class x { public: x() {}; x(int) : x() { throw std::exception(); } x(double) { throw std::exception(); } ~x(); };
what dynamic memory? exception in constructor means object not constructed , memory cleanedup , not lost.
but argument in previous question object constructed (or initialized) after delegate completes. how affect reclaiming memory? hope memory still cleanedup!
int main() { new x(5); // new called // delete called because delegate completed. // assume: // memory re-claimed (because constructor did not complete) // assume c++11 standard adjusted compensate. // constructor did complete. }
compared too:
int main() { new x(5.0); // new called // delete **not** called // memory re-claimed (because constructor did not complete) }
if memory cleaned up, definition of when memory cleanup needs altered c++03 spec. how behavior changed?
if constructor called new
throws exception memory allocated new
automatically deallocated. delegating constructors change nothing in regard.
if part of object initialization described above76 terminates throwing exception , suitable deallocation function can found, deallocation function called free memory in object being constructed
— c++11 [expr.new] 5.3.4/18
the 'any part of object initialization' described includes both constructor calls , evaluation of expressions passed constructor.
also, behavior specified identically in c++98 standard [c++98 5.4.3/17]. difference delegating constructors make if mental model based on object being constructed or not. given delegating constructors that's no longer equivalent actual specification of when deallocation occurs.
in first example:
new x(5);
the order of events is:
- allocation function called
- x(int) called
- x() called (and exits successfully)
- x(int) throws exception
- ~x() called
- x(int) exits via exception
- deallocation function called because object initialization failed
- exception continues propagate normally
with second example
new x(5.0);
- allocation function called
- x(double) called
- x(double) fails exception
- deallocation function called because object initialization failed
- exception continues propagate normally
you can observe behavior replacing allocation , deallocation functions:
#include <iostream> #include <cstdlib> #include <stdexcept> #include <new> void *operator new(std::size_t s) { if (void *ptr = std::malloc(s)) { std::cout << "allocation\n"; return ptr; } throw std::bad_alloc{}; } void operator delete(void *ptr) noexcept { if (ptr) { std::cout << "deallocation\n"; std::free(ptr); } } struct s { s() {}; s(int) : s{} { throw std::exception(); } s(double) { throw std::exception(); } ~s() { std::cout << "destructor\n"; } }; int main() { std::cout << "test 1\n"; try { new s(1); } catch(...) { std::cout << "exception caught\n"; } std::cout << "test 2\n"; try { new s(1.); } catch(...) { std::cout << "exception caught\n"; } }
the correct output of program is:
test 1 allocation destructor deallocation exception caught test 2 allocation deallocation exception caught
Comments
Post a Comment