#include <iostream>
struct A
{
A( int i ) : v(i)
{
if( v > 102 ) { std::cout << "\n*** throw ***\n\n" ; throw 100 ; }
std::cout << "A::constructor v == " << v << " -- " ;
}
~A() { std::cout << "A::destructor v == " << v << '\n' ; }
const int v ;
};
struct B
{
B( int i ) : a(i) { std::cout << "B::constructor: object at " << this << '\n' ; }
~B() { std::cout << "B::destructor: object at " << this << " -- " ; }
A a ;
};
struct C
{
C( int i ) : one(i), many { i+1, i+2, i+3, i+4 }
{ std::cout << "C::constructor\n" ; }
~C() { std::cout << "C::destructor\n" ; }
B one ;
B many[4] ;
static void* operator new( std::size_t sz )
{ std::cout << "\n+++ C::operator new\n\n" ; return ::new char[sz] ; }
static void operator delete( void* p )
{
std::cout << "\n+++ C::operator delete\n\n" ;
return ::delete static_cast<char*>(p) ;
}
// ... new[], delete[]
};
int main()
{
// no exceptions are thrown
try { C c1(0) ; std::cout << "ok\n" ; }
catch( int ) { std::cout << "constructor of c1 threw\n" ; }
// objects constructed are destroyed in reverse order
std::cout << "\n-------------------------------------\n" ;
// constructor of C : first construct members (5 object of type B)
// each constructor of B : first construct members (an object of type A)
// constructor of A
// after three objects of type B are created, C::one, C::many[0], C::many[1]
// the constructor of the fourth B C::many[2] =>
// constructor of A with i == 103 => which throws
// the objects which had been constructed are destroyed in reverse order
// of construction: C::many[1], C::many[0], C::one
// (each of which destroys the contained sub-object of type A)
try { C c2(100) ; std::cout << "ok\n" ; }
catch( int ) { std::cout << "\n*** constructor of c2 threw ***\n" ; }
std::cout << "\n-------------------------------------\n" ;
// same as above, the storage duration does not make a difference
// except that memory that was allocated by C::operator new
// would be released by C::operator delete
try { C* p = new C(100) ; std::cout << "ok\n" ; delete p ; }
catch( int ) { std::cout << "\n*** constructor of C threw ***\n" ; }
}