web-dev-qa-db-ja.com

C ++ 0xでnullptrを削除しても安全ですか?

c++03では、nullポインターを削除しても効果がないことは明らかです。実際、§5.3.5/2には次のことが明示的に記載されています。

どちらの方法でも、deleteのオペランドの値がNULLポインターである場合、操作は効果がありません。

ただし、現在の draft for c++0xでは、この文が欠落しているようです。ドラフトの残りの部分では、delete-expressionのオペランドがNULLポインター定数でない場合に何が起こるかを示す文のみを見つけることができました。 c++0xで定義されているNULLポインターを削除していますか?

注:

それがまだ十分に定義されていることを示唆する重要な状況証拠があります。

まず、§5.3.5/2には次の2つの文があります。

最初の選択肢(オブジェクトの削除)では、deleteのオペランドの値はNULLポインター値、...

そして

2番目の選択肢(配列の削除)では、deleteのオペランドの値はNULLポインター値または...

これらは、オペランドがnullであることを許可されていると言いますが、それ自体では実際に何が起こるかを定義していません。

第二に、delete 0の意味を変更することは重大な重大な変更であり、標準委員会がこの特定の変更を行うことはほとんどありません。さらに、c++0xドラフトのCompatibility Annex(Annex C)に重大な変更があるという言及はありません。ただし、付録Cは参考情報セクションであるため、これは規格の解釈には関係ありません。

一方、nullポインターを削除しても効果が得られないという事実は、追加の実行時チェックを意味します。多くのコードでは、オペランドがnullになることはないため、このランタイムチェックはゼロオーバーヘッドの原則と矛盾しています。委員会は、標準のC++を言語の指定された設計目標にさらに近づけるために、動作を変更することを決定したのでしょう。

69
Mankarse

5.3.5/7は言う:

Delete-expressionのオペランドの値がNULLポインター値でない場合、delete-expressionは割り当て解除関数(3.7.4.2)を呼び出します。それ以外の場合、割り当て解除関数が呼び出されるかどうかは指定されていません。

そして3.7.4.2/3はこう言います:

割り当て解除関数に提供される最初の引数の値は、nullポインター値である場合があります。その場合、および割り当て解除関数が標準ライブラリで提供されるものである場合、呼び出しは効果がありません。

そのため、標準の割り当て解除関数が使用されているか、ユーザー提供の割り当て解除関数がNULLポインターを正しく処理する限り、動作は適切に定義されます。

86
interjay

一方、nullポインターを削除しても効果が得られないという事実は、追加の実行時チェックを意味します。

新しい表現では、nullポインターの実行時チェックは削除されません。他の方法:ドラフト標準では、実装mustがnullポインターテストを準拠させると言うことにさらに近づきます。

また注目に値する:古い標準は(5.3.5/2)「削除のオペランドの値がNULLポインターである場合、操作は効果がない」と言ったという点で矛盾していましたが、後で(5.3.5/7) 「delete-expressionは割り当て解除関数を呼び出します。」関数の呼び出しは効果です。これは、呼び出される関数がオーバーライドされたoperator delete

新しい表現はその矛盾を取り除き、nullポインターを削除する場合に割り当て解除関数が呼び出されるかどうかを明示的に実装に任せます。

6
David Hammen