new A;した時にAのコンストラクタが例外を投げたらどうなるのか

C++でコンストラクタから例外を送出したい時 - 足跡の解決編です。
手元にあったC++Effective第三版の最後の方のページに全ての答えが書いてありました。
買った本はちゃんと全部読まないとダメですね。


コンストラクタから例外を送出する可能性のあるクラスAがあるとします。
このクラスを

A *obj = new A;

したとき、以下のような事が言えます。
まずnewはAのインスタンス用のメモリを確保してからAのインスタンスを確保したメモリ上に作成します。
なんらかの理由によってAのコンストラクタから例外が送出された場合、C++ランタイムはAのインスタンス用に確保されたメモリを破棄する為に、実行したnewに対応するdeleteを呼び出します。ただしAはインスタンス化していないのでデストラクタは呼ばれません。
これは特にクラス側でnewをオーバーライドしていなければ、C++標準のnewとdeleteのセットということになります。
このC++ランタイムから自動で呼ばれたdeleteによって、Aのインスタンス用に確保されたメモリ領域は破棄されます。
それに伴ってその時点でインスタンス化しているAの内部オブジェクト(メンバ)は全て破棄され各々のメンバのデストラクタが呼ばれます。
したがって、もしコンストラクタ内で動的に領域を確保していた場合、コンストラクタから例外が送出されると、ポインタ変数は破棄されますが動的に確保した領域はdeleteされず宙ぶらりんな状態になります。
また、A自体はデストラクタが呼ばれませんので、デストラクタにdelete用のコードを用意していても華麗にスルーされてしまうので注意が必要です。
なので、コンストラクタ内で動的に確保したメモリに関しては、コンストラクタ内で例外が発生した場合にコンストラクタ自身が責任を持って処分する必要があります。


なお、newがオーバーライドされていた場合、同一の引数を持つdeleteが存在しないとAのインスタンス用にnewが確保した領域は破棄される事なくメモリ上に存在し続けてしまいメモリリークしてしまいます。