placement newdelete (1) -- placement new

オブジェクトを動的に確保したり解放したりする場合は new / delete 演算子を使うわけだが、 デフォルトの new / delete 演算子を呼ぶと、 結局のところ malloc とか free に落ちることになるので、 ヒープ領域の管理コストがかかることになる。

たまに比較的大きなオブジェクトを生成するのに new を呼ぶ分にはそのコストも無視できるだろうが、サイズの小さい (たとえば、4バイトとか) オブジェクトを何百万回も生成 / 破棄するようなプログラムだと、 その時間的空間的な管理コストは無視できないほど大きくなる。

そのような場合に使われるのが、placement new (配置 new) というテクニックである。 次のようにふつうに new 演算子を使うと、

 X *x = new X;  
  1. まずデフォルトの operator new( size_t ) が呼び出され、
  2. そいつが返してくるメモリブロックに対してコンストラクタが適用される

という流れになる。 で、実のところ、この operator new はオーバーロードすることが可能だ。 たとえば、

  class X {
  public:
    static void *operator new( size_t size, void *buf ) { return buf; }
  };  

を定義しておけば、次のような呼び方が可能になる。

  char buffer[ sizeof(X) ];
  X *x = new( buffer ) X;  

こうすると、あらかじめ確保しておいたメモリ領域を使って、 そこにオブジェクトを構築することができる。

placement new の構文をより一般的に書くと次のようになる。

たとえば、TUV が型であるとして、

  class Y {
  public:
    static void *operator new( size_t size, T& t, U& u, V& v );
  };  

のような宣言があれば、

  T t;
  U u;
  V v;
  Y *y = new( t, u, v ) Y;  

といった呼び出しができるというわけである。この形でよく使われるのは、 自前でメモリアロケータのクラス (MyAllocator など) を用意しておいて、

  static void *operator new( size_t size, MyAllocator& allocator ) {
    return allocator.allocate( size );
  } 

などとするやり方だ。

さて、このような operator new を宣言した場合は、 それと対となる operator delete も宣言してやらねばならないのだが、 詳しくは次回。


初出: 2002年5月29日

C++ ラビリンスの目次へ


ホームページへ / Last modified: 2002-06-30 12:26:57 JST
Created by OKA Toshiyuki < oka-t@fides.dti.ne.jp >