#include <cstdlib>
#include <iostream>
#include <exception>
#include <new>
using namespace std;
#define TRACE() cout << __LINE__ << "\t" << __FUNCTION__ << endl
#define TRACE1(arg) cout << __LINE__ << "\t" << arg << endl
class AlBase {
protected:
AlBase() {}
~AlBase() {}
public:
static void* operator new(size_t size) {
TRACE();
if(size == 0) size = 1;
if(auto ptr = malloc(size)) return ptr;
throw bad_alloc();
}
static void operator delete(void* ptr) {
TRACE();
free(ptr);
}
};
class PAlBase {
protected:
PAlBase() {}
~PAlBase() {}
public:
static void* operator new(size_t, void* dst) {
TRACE();
return dst;
}
static void operator delete(void*, void*) {
TRACE();
}
};
class C1 {
public:
C1() { TRACE(); }
virtual ~C1() { TRACE(); }
};
class C2 : public C1, public AlBase {
public:
C2() { TRACE(); }
virtual ~C2() { TRACE(); }
};
class C3 {
public:
C3() { TRACE(); }
virtual ~C3() { TRACE(); }
};
class C4 : public C3 {
public:
C4() { TRACE(); }
~C4() { TRACE(); }
};
class C5 : public PAlBase {
public:
C5(bool raise = false) {
TRACE();
if(raise) throw 0;
}
~C5() { TRACE(); }
};
int main() {
TRACE1("--------");
{
// new -> C1.ctor -> C1.vtor -> delete
delete new C1;
}
TRACE1("--------");
{
// AlBase.new -> C1.ctor -> C2.ctor ->
// C2.vtor -> C1.vtor -> AlBase.delete
delete new C2;
}
TRACE1("--------");
{
// placement new -> C3.ctor -> C3.vtor
char t1[sizeof(C3)];
(new (t1) C3)->~C3();
}
TRACE1("--------");
{
// placement new -> C3.ctor -> C4.ctor -> C4.vtor -> C3.vtor
char t2[sizeof(C4)];
(new (t2) C4)->~C4();
}
TRACE1("--------");
{
// PAlBase.new -> C5.ctor -> C5.dtor
char t3[sizeof(C5)];
(new (t3) C5)->~C5();
}
TRACE1("--------");
{
// PAlBase.new -> C5.ctor -> throw ->
// C5.dtor + PAlBase.delete
char t4[sizeof(C5)];
try {
auto p5 = new (t4) C5(true);
p5->~C5(); // never arrive
} catch(int) {
TRACE1("* caught exception");
}
}
}