3

256 バイトのメモリ ブロックのみを割り当てたいとします。

char * memory = new char[256];

FooBar オブジェクトを作成するために新しい配置を使用するよりも (sizeof(Foobar)<=256)

FooBar * obj = new (memory) FooBar();

する

delete obj; //this also calls the destructor of FooBar

256 バイトのメモリをすべて削除しますか?

標準では、「obj を削除する」だけで「メモリ」バッファ全体の割り当てが解除されることが保証されていますか? または、タイプ「FooBar」に基づいているため、この操作の動作は未定義ですか?

仮定: FooBar はメモリ バッファー内の唯一のオブジェクトです。

これは重複した質問ではありません。まず質問を理解してください。このコードが何をするかはすぐにはわかりません。

4

2 に答える 2

6

C++ 標準は、あなたがしていることが未定義である理由を教えてくれます。によって呼び出される割り当て解除がdelete、割り当てられたブロックの先頭に追加されたサイズ情報を使用して適切に割り当て解除する場合がありますが、それに頼ることはできません。

§5.3.5 削除

delete-expression 演算子は、new-expression によって作成された最も派生したオブジェクト (1.8) または配列を破棄します。削除式:

  • ::キャスト式を削除
  • ::delete [ ] キャスト式

最初の選択肢は非配列オブジェクト用で、2 番目の選択肢は配列用です。delete キーワードの直後に空の角括弧が続く場合は常に、2 番目の選択肢として解釈されます。[...]

そうは言っても、ここでより興味深い部分に進みます。

2 [...] 最初の選択肢 (delete object) では、delete のオペランドの値は、null ポインター値、前の new 式によって作成された非配列オブジェクトへのポインター、またはそのようなオブジェクトの基底クラスを表すサブオブジェクト (1.8) (条項 10)。そうでない場合、動作は未定義です。[...]

  1. オブジェクトへのポインターは new 式によって作成されたのではなく、配置 new を介してオブジェクトの構築のみが行われました。
  2. アドレスのポインタobj(キャスト先void*と同じになるようにmemoryキャストするvoid*必要がありますが、それに頼ることさえできません)が指すポインタは、使用して割り当てられnew[]たため、使用delete[]は必須です。

関連する質問を参照してください。


同じタイプの複数のオブジェクトに事前に割り当てられたストレージが必要な場合: の使用を検討してstd::vector<FooBar>::reserve()ください。

emplace_back()またはpush_back()、オブジェクトのインプレース構築を行います。

于 2013-07-08T05:35:01.720 に答える