c++ - Is the memory automatically reclaimed when a delegating constructor throws? -


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