すんまそん、って昔流行ったような流行らないような

id:arCtan:20051010やid:arCtan:20051103あたりでかなりでたらめなことを書いてたっぽいので訂正。
placement new/deleteのことを自分は「独自のメモリ確保・解放を行うためのoperator new/deleteのオーバーロードのこと」と捉えていたが、どうも正しくなかったようだ。
operator new/deleteは第2引数以降を任意に指定して定義できる。その中でも特に第2引数をvoid*として定義し、渡したメモリブロックをそのままオブジェクト構築用の領域として使うoperator new/deleteの定義のことを、一般に「placement new/deleteの手法」と呼ぶらしい。そしてこの手法がかなり一般的なことから、VisualC++などのコンパイラのヘッダファイルの中にもそういうoperator new/deleteが既に定義されていることが多いということらしい。
したがって、自分がやっていた「第2引数以降は指定せずに、メモリ確保・解放の仕方をグローバルの::operator new/deleteとは別の方法で行う」というのは、単なる個人的なoperator new/deleteのオーバーロードに過ぎなかったというわけだ。
いやー、中途半端に理解してモノを書くと同時に恥もかきますね(つ∀`)


それともう一つ。
これも当時はいまいち理解できなかったのだが、第2引数以降を指定したoperator deleteの定義は、delete演算子と関連付けられない。
delete演算子は型に合ったoperator deleteを呼び出す前に、暗黙的にデストラクタを呼び出すという重要な役割を自動的に行う。同様にnew演算子は型に合ったoperator newを呼び出した後、暗黙的にコンストラクタを呼び出す。しかし、第2引数以降が指定されたoperator newが定義されている場合、new演算子にその引数を指定できるのだが(その引数は暗黙的にoperator newに渡される)、なぜだかdelete演算子はできない。

class CHoge{
public:
 //第2引数以降は型はなんでもよい
 static void* operator new(size_t size, T& t){/*なんやかんや*/}
 static void  operator delete(void*p, T& t){/*あれこれ*/}
};

T t;                        //なんか適当なオブジェクト

CHoge* p = new(t) CHoge;    //可
delete(t) p;                //ダメ。構文エラー

これはかなり困った仕様だと思うのだが、そのかわり、デストラクタはコンストラクタと違って個別に明示的に呼び出すことができる。よって、第2引数以降を指定したoperator deleteを定義するときは、解体時にデストラクタの明示的呼び出しと、operator deleteの呼び出しを両方行う必要がある

p->~CHoge();
CHoge::operator delete(p,t);    //これでおk

めんどい仕様ですな。
といっても、上で触れたplacement new/deleteのような場合はoperator deleteの2番目の引数を使用する必要がない(解放すべきメモリはすでに第1引数に渡っている)ので、こういうときは第1引数のみのoperator deleteもオーバーロードしておけば、delete演算子が使えるので上のようなめんどうな別個呼び出しを回避できる。

class CHoge{
public:
 //placement new/deleteの場合
 static void* operator new(size_t size, void*buf){ return buf; }
 static void  operator delete(void*p, void*buf){ /*なんもやることない(^^;*/ }
 static void  operator delete(void*p){ /*上に同じ(^^;*/ }
};

BYTE buffer[sizeof(CHoge)];       //適当に領域確保じゃ

CHoge* p = new(buffer) CHoge;     //可
delete p;                         //可。どうせ第2引数使わないし〜

ところでこれなら第2引数付きのoperator deleteは要らないんじゃないの?と思うかもしれないが、オブジェクトのコンストラクト中に例外が発生すると、使用されたoperator newと第2引数の型が同じoperator deleteが自動的に呼び出される仕組みになっているようなので、一応あったほうがいいんじゃないんでしょうか、ということらしいです。


ふう。なんかほとんど参考文献の丸写しみたいだけど、一応俺向きに噛み砕いてみたつもり。ではおやすみ(・ω・)ノシ


参考文献
http://www.fides.dti.ne.jp/~oka-t/cpplab-placement-new-2.html
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpdndeepc/htm/deep071599.asp
http://www.geocities.jp/ky_webid/cpp/language/036.html