In the code that follows, the object sub
in class C
is constructed twice. The first construction calls the default ctor Sub()
and the second construction uses placement new
to reconstruct this object in the same address.
Therefore the destructors are also called twice. The first call uses the direct call to the Sub
dtor in ~C()
and the second call is invoked after the end of main()
, I believe, by the atexit()
function.
Given that the object sub
is reconstructed at the same address, how does the compiler knows that the second destructor must be called after main()
? Where does he keep this information?
#include <iostream>
using namespace std;
struct Table
{
int i;
Table(int j) : i(j) {}
};
struct Sub
{
Table* pTable;
Sub(int j) { cout << "ctor placement new" << endl; pTable = new Table(j); }
Sub() { cout << "ctor default" << endl; pTable = 0; }
~Sub() { if( pTable ) cout << "dtor placement new" << endl;
else cout << "dtor default" << endl;
delete pTable; pTable = 0; }
};
class C
{
Sub sub;
public:
C() { new (&sub) Sub(10); }
~C() { (&sub)->~Sub(); }
};
int main()
{
C c;
}
Although this is clearly undefined behavior, if you reason out what's happening, it's pretty obvious.
You create an object of class C. In that process, the default constructor of Sub is called implicitly. pTable is 0. Then, you explicitly call the int constructor, which initializes pTable. Then, in the destructor, you explicitly call Sub's destructor. pTable is set to 0 again. Then, at the end of C's destructor, Sub's destructor is called again, implicitly.
It's not at the end of main that it's happening. It's happening at the end of C's destructor.