8

:: deleteに渡された左辺値を変更する最初のコンパイラーに遭遇しましたが、左辺値をゼロにしません。それは次のとおりです。

 Foo * p = new Foo();
 Foo * q = p;
 assert(p != 0);
 assert(p == q);
 ::delete p;
 assert(p != q);
 assert(p != 0);

削除操作後のpはゼロではなく、古い値から変更されていることに注意してください。同僚は、pを0xFFFFFFFFに変更するメインフレームC ++コンパイラや、pを0に変更する他のコンパイラを使用した経験では、これは珍しいことではないと私に言いました。

C ++標準のどこで、コンパイラがこれを実行できると言っていますか?

StackOverflowを検索すると、次の質問が見つかりました。削除してポインタをNULLに設定しないのはなぜですか。これには、次のステートメントを含むBjarneStroustrupの応答を参照する回答がありました。

C ++では、削除の実装で左辺値のオペランドをゼロにすることが明示的に許可されており、実装でそれができることを期待していましたが、そのアイデアは実装者に普及していないようです。

最終委員会ドラフトC++0x標準のセクション5.3.5および12.5を読み直しましたが、「明示的な」部分が表示されていません。標準の間違ったセクションを見ているだけですか?または、セクションにロジックのチェーンがありますが、正しく接続されていません。

AnnotatedC++リファレンスマニュアルのコピーはもうありません。コンパイラがこれを実行できるのはARMでしたか?

[編集:セクション参照を3.5.3から5.3.5に修正。また、削除後にpが未定義であるというヘンクの主張に対する対位法として、興味深いパラドックスを追加しています。]

pがnullに初期化される場合、興味深いパラドックスがあります。

 Foo * p = 0;
 Foo * q = p;
 assert(p == 0);
 assert(p == q);
 ::delete p;
 assert(p == q);
 assert(p == 0);

ただし、この場合、動作は十分に文書化されています。deleteがnullポインターを取得すると、何もしないと想定されるため、pは変更されません。

4

1 に答える 1

8

それほど明確ではないかもしれません。5.3.5 / 7では、delete式がdeallocator関数を呼び出すことを示しています。次に、3.7.3.2 / 4では、割り当てが解除されたポインタの使用は未定義であると表示されます。割り当て解除後にポインタの値を使用することはできないため、ポインタが値を保持するか、実装によって値が変更されるかは違いはありません。

5.3.5 / 7

delete-expressionは、割り当て解除関数(3.7.3.2)を呼び出します。

3.7.3.2 / 4

標準ライブラリの割り当て解除関数に指定された引数がnullポインタ値(4.10)ではないポインタである場合、割り当て解除関数は、ポインタによって参照されるストレージの割り当てを解除し、ポインタのいずれかの部分を参照するすべてのポインタを無効にします。割り当て解除されたストレージ。無効なポインター値を使用した場合の影響(割り当て解除関数への受け渡しを含む)は未定義です。

参照は現在の標準からのものです。今後の標準では、5.3.5/7が言い換えられました。

C ++ 0x FD 5.3.5 / 7

delete-expressionのオペランドの値がnullポインター値でない場合、delete-expressionは割り当て解除関数(3.7.4.2)を呼び出します。それ以外の場合は、割り当て解除関数が呼び出されるかどうかは指定されていません。[注:割り当て解除関数は、オブジェクトのデストラクタまたは配列の一部の要素が例外をスローするかどうかに関係なく呼び出されます。—エンドノート]

于 2010-08-02T22:05:13.267 に答える