8

プールされた固定ブロック メモリ アロケータをアップグレードして、C++11 の型特性を利用する実験を行っています。

現在、従来の方法でグローバル new 演算子をオーバーライドすることにより、任意のオブジェクトの任意の割り当てを正しいプールに強制的にディスパッチすることができます

void* operator new (std::size_t size) 
{ // if-cascade just for simplest possible example
   if ( size <= 64 ) { return g_BlockPool64.Allocate(); }
   else if ( size <= 256 ) { return g_BlockPool256.Allocate(); }
   // etc .. else assume arguendo that we know the following will work properly
   else return malloc(size);
}

などの型特性に応じてオブジェクトを異なるプールにディスパッチできれば、多くの場合、パフォーマンスをさらに向上させることができますis_trivially_destructible要求されたサイズだけでなく、割り当てられた型を認識するテンプレート化されたグローバル new 演算子を作成することは可能ですか? に相当するもの

template<class T>
void *operator new( size_t size)
{
  if ( size < 64 ) 
  {  return std::is_trivially_destructible<T>::value ? 
            g_BlockPool64_A.Allocate() : 
            g_BlockPool64_B.Allocate(); } //  etc
}

すべてのクラスで member new 演算子をオーバーライドしても、ここでは機能しません。これは、どこにある割り当てでも自動的に機能するために本当に必要です。配置 new も機能しません。すべての alloc が次のように見える必要があります

Foo *p = new (mempool<Foo>) Foo();

面倒すぎて、人々はそれを使うのを忘れてしまいます。

4

1 に答える 1

3

短い答えはノーです。割り当て/割り当て解除関数には、次のシグネチャがあります。

void* operator new(std::size_t);
void* operator new[](std::size_t);
void operator delete(void*);
void operator delete[](void*);

これらの署名からほとんど逸脱すると、関数がまったく使用されなくなります。典型的な実装では、基本的にリンカ レベルでデフォルトの実装を置き換えます。つまり、既存の関数には特定のマングル名があります。同じ結果にマングルする名前の関数を指定すると、代わりにリンクされます。関数が同じ名前にマングルしないと、リンクされません。

あなたが提案したようなテンプレートは、場合によっては使用されるかもしれませんが、そうであれば、未定義の動作につながります。ヘッダーの配置方法によっては (たとえば)、テンプレートの使用とデフォルトの関数が混在するコードになる可能性があります。

于 2013-05-25T00:16:25.383 に答える