web-dev-qa-db-ja.com

C ++ new int [0]-メモリを割り当てますか?

簡単なテストアプリ:

cout << new int[0] << endl;

出力:

0x876c0b8

そのため、機能しているように見えます。これについて規格は何と言っていますか?空のメモリブロックを「割り当てる」ことは常に合法ですか?

224
anon

5.3.4/7から

Direct-new-declaratorの式の値がゼロの場合、要素なしで配列を割り当てるために、割り当て関数が呼び出されます。

3.7.3.1/2から

サイズ0の要求として返されるポインターの逆参照の効果は定義されていません。

また

[by new]で要求されたスペースのサイズがゼロであっても、要求は失敗する可能性があります。

つまり、それを行うことはできますが、合法的に(すべてのプラットフォームで明確に定義された方法で)取得したメモリを逆参照することはできません-配列削除にのみ渡すことができます-そして削除する必要があります。

3.7.3.1/2の文に添付されている興味深い脚注(つまり、標準の規範的な部分ではなく、説明目的で含まれています)を示します。

[32。目的は、malloc()またはcalloc()を呼び出すことにより、演算子new()を実装できるようにすることです。したがって、ルールは実質的に同じです。 C++は、Null以外のポインターを返すためにゼロ要求を要求する点でCと異なります。]

226
Faisal Vali

はい、このようなゼロサイズの配列を割り当てることは合法です。ただし、それも削除する必要があります。

21
anon

これについて規格は何と言っていますか?空のメモリブロックを「割り当てる」ことは常に合法ですか?

すべてのオブジェクトには一意のID、つまり一意のアドレスがあり、これはゼロ以外の長さを意味します(ゼロバイトを要求すると、実際のメモリ量は静かに増加します)。

これらのオブジェクトを複数割り当てた場合、異なるアドレスを持っていることに気付くでしょう。

15
ChrisW

はい、0サイズのブロックをnewで割り当てることは完全に合法です。アクセスできる有効なデータがないため、単に有用な操作を行うことはできません。 int[0] = 5;は違法です。

ただし、標準ではmalloc(0)のようなものがNULLを返すことが許可されていると思います。

delete []割り当てから戻されるポインターも同様に必要です。

14
Evan Teran

興味深いことに、C++では、ゼロバイトが要求された場合でも、演算子newが正当なポインターを返す必要があります。 (この奇妙な響きの振る舞いを必要とすることで、言語の他の部分が単純化されます。)

Effective C++ Third Editionは、「項目51:新規作成および削除時の規約に従う」でこのように述べています。

1
shuaihanhungry