placement new
言語処理系のGC
俺Lispのインタプリタを書いていて、stop and copyのGCを書くためにplacement new
を勉強してました。
でも、試行錯誤してるうちに気づいたら使ってなかった…orz。
せっかくなので、placement new
についてまとめ。
詳しくはEffective C++ 第3版を参照。
Effective C++ 原著第3版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
- 作者: スコット・メイヤーズ,小林健一郎
- 出版社/メーカー: ピアソン・エデュケーション
- 発売日: 2006/04/29
- メディア: 大型本
- 購入: 29人 クリック: 411回
- この商品を含むブログ (186件) を見る
placement new
の説明
まず、基本的なところからいくと、C++においてはメモリ確保と初期化は別物。前者がoperator new
、後者がコンストラクタです。
operator new |
サイズ(std::size_t 型)を受け取り、メモリ領域を返す |
コンストラクタ | 確保されたメモリ領域にオブジェクトを構築する |
そして、operator new
をオーバーロードするといろいろなトリックが使えるようになるのですが、これを可能にするのがplacement new
と呼ばれるテクニック((placement new
の定義は多少あいまいで、単純にoperator new
をオーバーロードする場合もあれば、サイズ以外の情報を取るoperator new
のことを指す場合もある))です。特に、operator new
にメモリ領域を渡して、それをそのままオブジェクトに渡すというパターンがもっとも良く使われます。これによって、任意のメモリ領域にオブジェクトを構築することができます。
この、一番良く使う「あらかじめ用意したメモリ領域にオブジェクトを構築する」パターンの例。よく使うだけあって(たぶん)、すでに標準で用意されています。
// test.cpp #include<iostream> #include<new> using namespace std; // 整数加算を蓄積するクラス class Acc { int _val; public: // コンストラクタとデストラクタ Acc(int val=0) : _val(val) {} ~Acc() { } int call(int v=0) { _val += v; return _val; } }; int main() { // Accクラスのサイズ分のメモリを確保し、そこにAccオブジェクトを構築する char *p = new char[sizeof(Acc)]; // <new>ヘッダであらかじめ用意されているplacement new。 Acc *a = new(p) Acc; cout << a->call(3) << endl; cout << a->call(7) << endl; // オブジェクトの破壊とメモリの開放は今や別処理。 a->~Acc(); delete[] p; return 0; }
実行結果。
$ g++ test.cpp && ./a.out 3 10