長さがゼロの配列へのポインタのプロパティ


21

検討する

int main()
{
    auto a = new int[0];
    delete[] a; // So there's no memory leak
}

コピーの初期化から削除までの間に、ポインタを読み取ることができますa + 1か?

さらに、この言語では、コンパイラーをに設定aできnullptrますか?


2
@Fareanor:あなたはa確かに読むことができます(確かにそれを逆参照することはできません)。
バトシェバ

8
@RasmiRanjanNayak:それは大食いです。
バトシェバ

2
@RasmiRanjanNayak Oh my ...いいえ
Ted Lyngmo

1
@TedLyngmo:「ポインタを読む」と言うa + 1と、次のコードはauto b = a + 1;未定義の動作ですか?(それはそうですね)。
バトシェバ

2
@Ayxan 0実際には、実行時までわからないある式の結果である場合に推測します。のでnew int[0]安全です、それはあなたには、いくつかの分岐/特殊なケースを心配救うことができます。std::vectorwith を初期化する場合を想像してみてくださいstd::vector<int> v(0);
scohe001

回答:


3
    auto a = new int[0];

[basic.compound.3]によると、格納される値aは次のいずれかである必要があります:

  1. (型のint)オブジェクトへのポインタ
  2. オブジェクトの終わりを過ぎたポインタ
  3. ヌル
  4. 無効

int構築されたタイプのオブジェクトがなかったので、最初の可能性を除外できます。C ++ではnull以外のポインターを返す必要があるため、3番目の可能性は除外されます([basic.stc.dynamic.allocation.2]を参照)。したがって、2つの可能性があります。オブジェクトの終わりを過ぎたポインタまたは無効なポインタです。

私はa過去の終わりのポインタと見なす傾向がありますが、それを明確に確立する信頼できるリファレンスはありません。(ただし、これは[basic.stc]で強く示唆されており、どのようにしてdeleteこのポインターを使用できるかがわかります。)したがって、この回答では両方の可能性について説明します。

コピーの初期化から削除までの間に、ポインタを読み取ることができますa + 1か?

[expr.add.4]示されているように、上記のどの可能性が適用されるかに関係なく、動作は未定義です。

場合a過去エンドポインタである、それはインデックスで仮説の要素を指すように考えられて0ない要素を持つ配列の。jへの整数の追加は、が配列のサイズであるa場合0≤0+j≤nにのみ定義されnます。我々の場合には、nその合計は、ゼロであるa+jときにのみ定義されてjいます0。特に、追加1は未定義です。

aが無効な場合は、「それ以外の場合、動作は未定義」に完全に分類されます。(当然のことながら、定義されているケースは有効なポインター値のみをカバーしています。)

さらに、この言語では、コンパイラーをに設定aできnullptrますか?

いいえ。上記の[basic.stc.dynamic.allocation.2]から「リクエストが成功した場合、置き換え可能な割り当て関数によって返される値はnull以外のポインタ値です。C ++(ただしCではない)がゼロ要求に応答してnull以外のポインターを必要とすることを示す脚注もあります。


1
無効なポインタ値の場合、eel.is / c ++ draft / basic.stc#4
TC

@TC True、それはそれが無効なポインタ値であってはならないことを強く意味します。
JaMiT

23

編集上の問題3178の結果としての最近のCWGリフレクターの議論によるnew int[0]現在「過去の終わり」のポインター値と呼ばれているものが生成されます

これはanullにすることはできずa + 1[expr.add] / 4で定義されていません。


4
「編集上の問題3178の結果としての最近のCWGリフレクターの議論によれば、new int[0]現在「過去の終わり」のポインター値と呼ばれているものが生成されます」これは正確ではありません。あまり議論はありませんでした。ある人は、値は「オブジェクトの終わりを過ぎたポインタ」であるべきだと提案しましたが、0要素を持つ配列の場合、終わりを過ぎたオブジェクトがないため、このステートメントは疑問視されました。
言語弁護士

@LanguageLawyer a + 1どんな場合でも未定義であることに疑いがないように思われるので、あなたのポイントはanullになることができるかどうかにのみ関係しますか?
MM

意図されたセマンティクスについて不一致はないようであり、このポインター値のカテゴリーの現在の名前は、このシナリオにはあまり適していません。
TC

@MMこれa + 1は未定義であり、結果として得られるポインタ値は「最後を過ぎたポインタ」と呼ばれるでしょう。答えが間違っていると言っているのではありません。結果が「最後を過ぎたポインタ」であることを指定するだけで問題を解決できるというコンセンサスとの長い議論があったと理解できるため、少し正確ではありません。「ポインタが最後を超えている」の問題は、オブジェクトの最後を超えており1、そのようなポインタ値から差し引くと、オブジェクトへのポインタが与えられること0です。これは、要素の配列の場合には当てはまりません。
言語弁護士

2
@Bathsheba言葉遣いの欠陥についてもっと権威のあることがあると思いますか?
言語弁護士
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.