一般的なメモリ割り当ての問題は、驚くほど難しい問題です。解決したと考える人もいれば、解決できないと考える人もいます;)内部に興味がある場合は、まずDougLeaのmallocを見てください。
特殊なメモリアロケータは、通常、はるかに単純です。単純さとパフォーマンスのために、一般性(サイズを固定するなど)と引き換えになります。ただし、現実的なプログラムでは、通常、一般的なメモリ割り当てを使用する方が、特別なアロケータの寄せ集めよりも優れていることに注意してください。
メモリアロケータの「魔法」を介してメモリのブロックが割り当てられると、配置newを使用してコンテナの自由に初期化できます。
- - 編集 - -
newの配置は、「通常の」プログラミングには役立ちません。メモリ割り当てをオブジェクトの構築から分離するために独自のコンテナを実装する場合にのみ必要になります。そうは言っても、配置を使用するための少し工夫された例を次に示します。
#include <new> // For placement new.
#include <cassert>
#include <iostream>
class A {
public:
A(int x) : X(x) {
std::cout << "A" << std::endl;
}
~A() {
std::cout << "~A" << std::endl;
}
int X;
};
int main() {
// Allocate a "dummy" block of memory large enough for A.
// Here, we simply use stack, but this could be returned from some allocator.
char memory_block[sizeof(A)];
// Construct A in that memory using placement new.
A* a = new(memory_block) A(33);
// Yup, it really is constructed!
assert(a->X == 33);
// Destroy the object, wihout freeing the underlying memory
// (which would be disaster in this case, since it is on stack).
a->~A();
return 0;
}
これは印刷します:
A
~A
---編集2---
OK、これがアレイに対してどのように行うかです:
int main() {
// Number of objects in the array.
const size_t count = 3;
// Block of memory big enough to fit 'count' objects.
char memory_block[sizeof(A) * count];
// To make pointer arithmetic slightly easier.
A* arr = reinterpret_cast<A*>(memory_block);
// Construct all 3 elements, each with different parameter.
// We could have just as easily skipped some elements (e.g. if we
// allocated more memory than is needed to fit the actual objects).
for (int i = 0; i < count; ++i)
new(arr + i) A(i * 10);
// Yup, all of them are constructed!
for (int i = 0; i < count; ++i) {
assert(arr[i].X == i * 10);
}
// Destroy them all, without freeing the memory.
for (int i = 0; i < count; ++i)
arr[i].~A();
return 0;
}
ところで、デフォルトのコンストラクターがある場合は、このようなすべての要素で呼び出すことA
ができます...
new(arr) A[count];
...しかし、これはあなたが本当に扱いたくないワームの缶を開くでしょう。