質問: new(&base) CBase(5); placementBase->~CBase(); CBase::operator delete(placementBase, &base); } ``` そもそも、ローカル変数のオブジェクトに対してplacement newを使用することが、非常に奇妙なことだと思いますが、それは前提としてください。 以上、宜しくお願い致します。
回答: こんにちは。 通常new/deleteは、メモリの獲得/解放とオブジェクトの構築/解除をセットで行います。 new=メモリの獲得+オブジェクトの構築、delete=オブジェクトの解除+メモリの解放ですね。 このセットを崩すと有用なケースが有るのだと思います。メモリの獲得/解放はmalloc/free等でできますので、オブジェクトの構築と解放だけを呼ぶ方法を作ったのでしょう。 それがプレイスメントnewとデストラクタの直接呼び出しと思います。 コンストラクタの直接呼び出しを許さなかったのは、コンストラクタにメモリ・ポインタを追加する必要があり、全てのコンストラクタを2セット用意することになるので採用しなかったのだと思います。 > > 意図としては、new(&base) CBase(5)がデストラクタを呼ぶことを期待しているため、何か違和感を感じます。 > > > プレイスメントnewやデストラクタの直接呼び出しは、いつも行うメモリ獲得/解放とオブジェクトの構築/解除のセットを崩すので、違和感を感じるのではないでしょうか? デストラクタの直接呼び出しを行った時点でその違和感は許容すべきことのように感じます。 > > この場合、コンストラクタは2回呼ばれ、デストラクタは3回呼ばれます。 > > しかも、placement deleteが呼ばれた後に、デストラクタが呼ばれるため、違和感を感じます。 > > > `CBase base(3);`のスコープを外れた時に、これに対応するデストラクタを呼ぶコードをコンパイラは作ります。例外処理対応等も考慮したスタックの巻き戻しの仕組みも準備している筈です。 `base.~CBase();`のコードは、if文で呼んだり呼ばなかったりすることができます。それぞれに対応して上記のデストラクタ呼び出しを有効にしたり無効にしたりするのは、C++言語の主義に反するように感じます。(デストラクト済フラグは持ってないですから。) ですので、私は現仕様は素直な印象を受けています。使うかどうかは別として。 プレイスメントnewを使うとスタック上のオブジェクトに対して、遅延コンストラクトが可能になるので何か有用な使い方もありそうな気もします。遅延コンストラクト用のクラス・テンプレートを作れば可読性も悲惨なことにはならないで済むかも? でも、多くのケースでstd::unique_ptr<>を使えば十分な気がします。