2行目は何ですか?(別の質問に答えているときに表示されます。)
int * x = new int [1] ;
int * y = new (x) int;
2行目以降、xとyは同じ値になります(同じ場所を指します)。y = xと2行目の違いは何ですか?コンストラクターか何かのようなものですか?
2行目は何ですか?(別の質問に答えているときに表示されます。)
int * x = new int [1] ;
int * y = new (x) int;
2行目以降、xとyは同じ値になります(同じ場所を指します)。y = xと2行目の違いは何ですか?コンストラクターか何かのようなものですか?
新しい配置です。int
が指すメモリに新しいものを作成しx
ます。
試してみると:
int * x = new int [1];
*x = 5;
std::cout << *x << std::endl;
int * y = new (x) int;
*y = 7;
std::cout << *x << std::endl;
出力は次のようになります。
5
7
これは、配置新規と呼ばれます。これにより、すでに割り当てられているメモリ内にオブジェクトを作成できます。
この以前のスレッドでは、それがどこでどのように役立つかについて説明しています。
2番目の新しいものは「新しい配置」です。割り当てを行わずに初期化を実行します(つまり、必要なコンストラクターを呼び出します)。カスタムメモリ割り当てスキームを作成する必要がある場合に便利です。
これは新しい配置です。
ただし、通常は整数型では使用しません。
これは通常、他のタイプを組み込むバッファを構築するために使用されます。
// Allocate a buffer with enough room for two T objects.
char* buffer = new char[sizeof(T) * 2];
// Allocate a T in slot zero
T* t1 = new (buffer + 0 * sizeof(T)) T("Zero");
// Allocate a T in slot one
T* t2 = new (buffer + 1 * sizeof(T)) T("One");
それが基本です。
ただし、配置newで割り当てられたオブジェクトは、ステートメントでは削除できないことに注意してください。delete
これは、delete
によって割り当てられたメモリを再利用しようとするためですnew
(また、デストラクタを呼び出します)。したがって、これらのオブジェクトを正しく使用するには、手動でデストラクタを呼び出す必要があります。
t1->~T();
t2->~T();
元のバッファを削除することを忘れないでください。
delete [] buffer;
その他の注意点:
多くの場合、バッファはスタックに実装され、自動的に解放される可能性があります。
char buffer[sizeof(T) * 2];
残念ながら、これは技術的には問題ないかもしれません(コンパイルされます)。ただし、Tを内部に配置するには、バッファのメモリが正しく配置されていない可能性があるため、動作が保証されていません。したがって、バッファを動的に割り当てる必要があります(newを使用すると、割り当てられたサイズのオブジェクトに対してメモリが正しく配置されることが保証されます(したがって、拡張により、割り当てられたサイズよりも小さいサイズに対しても調整されます)。簡単に回避できます。この問題は、std::vectorを使用することです。
std::vector<char> buffer(sizeof(T) * 2);
T* t1 = new (&buffer[0] + 0 * sizeof(T)) T("Zero");
T* t2 = new (&buffer[0] + 1 * sizeof(T)) T("One");
new配置の別の使用法は、オブジェクトをリセットすることです。
私はこれが行われるのを見てきましたが、より標準的な代入演算子を使用することを好みます。
T obj1("Plop");
obj1 = T("Another Plop");
// Can be done like this:
T obj1("Plop");
obj1.~T();
new (&obj1) T("Another Plop"); // Seems excessive to me. But can be us-full
// in some extreme situations.
リセットメソッドを使用する場合は、最初に古いオブジェクトを破棄する必要があることに注意してください(そうしないと、オブジェクトが正しく動作しない可能性があります)。
int * y = new (x) int;
これは、配置の新しい構文によるものです。
編集:カスタム割り当てに加えて、新しい配置は、以下のようにオブジェクトの状態を再初期化するのにも役立ちます。
class Test
{
int startVal;
public:
Test()
{
startVal = 1;
}
void setVal(int val) { startVal = val; }
};
int main()
{
Test *p = new Test; //Creates new object and initializes it with
//a call to constructor.
p->setVal(10); //Change object content.
new(p) Test; //Reset object:
//object pointed by p will be re-initialzed here by making
//a call to constructor. startVal will be back to 1
}
上記のコメントで説明したように、オブジェクトの状態のリセットは、配置新規を使用して実現することもできます。new配置はメモリを割り当てず、パランセシスの指定されたアドレスにオブジェクトを構築します。