これを理解するには、まず単純で単純なnew
仕組みを理解する必要があります。式の通常の構文new
は次のようなものnew T
です。式を使用するnew
と、次のことが起こります。
まず、割り当て関数を呼び出して、オブジェクトのストレージを取得します。割り当て関数は、要求されたオブジェクトに適合するのに十分な大きさの割り当てられたストレージへのポインターを返す必要があります。これ以上のことはしません。オブジェクトを初期化しません。
次に、割り当てられた領域でオブジェクトが初期化されます。
割り当てられた領域 (および初期化されたオブジェクト) へのポインターが返されます。
の場合new T
、割り当て関数の名前はoperator new
です。などの配列を割り当てる場合new T[5]
、割り当て関数には という名前が付けられoperator new[]
ます。これらの関数の既定の定義は、グローバル名前空間で提供されます。std::size_t
それらはそれぞれ、必要なバイト数であるタイプの単一の引数を取ります。したがって、 を実行するnew T
と、対応する呼び出しは になりますが、operator new(sizeof(T))
forは呼び出されます。new T[5]
operator new[](sizeof(T)*5)
ただし、割り当て関数にさらに多くの引数を渡すことは可能です。これは、配置の新しい構文として知られています。より多くの引数を渡すにはnew (some, arguments, 3) T
、 を呼び出すso: のような構文を使用しますoperator new(sizeof(T), some, arguments, 3)
。new
引数のリストは、 と タイプの間の括弧で囲みます。
どちらも実装によって提供される単純なoperator new(std::size_t)
配列とそれに対応する配列に加えて、 type の追加の引数を取るデフォルトの定義もありますvoid*
。つまり、オブジェクトへのポインタを取ります。これらの関数は実際にはスペースを割り当てず、指定したポインターを返すだけです。したがって、 を実行するnew (some_pointer) T
と、最初に が呼び出さoperator new(sizeof(T), some_pointer)
れsome_pointer
、再び戻り、次にその空間でオブジェクトが初期化されます。これにより、すでに割り当てられている領域でオブジェクトを初期化する方法が提供されます。
これで、次の 4 つの定義済み割り当て関数ができました (実際、他にもいくつかあり、独自のものも自由に定義できます)。
// Normal allocation functions that allocate space of the given size
operator new(std::size_t)
operator new[](std::size_t)
// Placement allocation functions that just return the pointer they're given
operator new(std::size_t, void*)
operator new[](std::size_t, void*)
それでは、あなたが提供したコードスニペットを見てみましょう:
void * memory = operator new[] (10*sizeOf(MyClass));
MyClass * myArray = static_cast<MyClass*>(memory);
for(int i= 0; i<10; i++)
{
new (&myArray[i]) MyClass(params);
}
operator new[]
最初の行では、ストレージを割り当てるために直接呼び出しています。収納量は?タイプ のオブジェクトが 10 個あれば十分ですMyClass
。この関数は、その割り当てられたストレージへのポインターを返し、それを に格納しますmemory
。
この後、void*
は a にキャストされ、MyClass*
サイズ のブロックで割り当てられたストレージにインデックスを付けることができますsizeof(MyClass)
。つまりmyArray[0]
、最初MyClass
とmyArray[1]
2 番目を指すようになります。
次に、その配列をループし、割り当てられたストレージの初期化されていないサイズの各ビットのアドレスを使用して、placement newを呼び出します。MyClass
たとえば、最初の繰り返しでは、これは割り当て関数operator new(sizeof(MyClass), &myArray[0])
を呼び出します。これは、前に見たように、指定したポインターを返すだけです。新しい式はMyClass
、この空間でオブジェクトを初期化し、ポインタを返すことで完了します。
要約すると、コードは 10 個MyClass
のオブジェクトに適合するようにストレージを割り当て (ただし、初期化はしません)、MyClass
そのストレージ内の の各サイズのスペースをループして、それぞれのオブジェクトを初期化します。
これは、事前に割り当てられたストレージでオブジェクトを初期化する方法を示しています。新しく初期化されたオブジェクトで同じストレージを何度も再利用できます。