C ++で有効な操作であることが必要であるとどこかで読んだことを覚えていますdelete NULL
が、そうする必要がある理由を思い出せません。誰か思い出してくれませんか?
7 に答える
正確な理由:
- C++ 標準委員会がそう決定したからです。
考えられる理由:
delete
ユーザー コードを呼び出す前にすべてのポインターの NULL をチェックするのは、コードの肥大化が大きすぎるためです。
規則がなくても言語が存在する可能性があるという点で、規則は厳密には必要ではありません。これは単に標準化委員会によって下された決定です。NULL ポインタは有効なメモリ アドレスではありません。ただし、それぞれの決定には理由があり、その理由は知っておく価値があると信じたいと思います。
このルールは、失敗のケースや、ポインターが null になる可能性があるその他のインスタンスの管理を簡素化します。これは簡単で安価なチェックであり、言語にかなりの利便性を追加します。
たとえば、動的メモリ割り当てが発生する多くの条件が存在するが、そうでない条件も存在する場合delete
、最後に a を貼り付けて気にしないで済むと便利です。
// contrived example
void foo(int n) {
char *p = nullptr;
switch(n) {
case whatever:
case something_else:
p = new char[n];
break;
}
// some code...
delete [] p; // look Ma, no check!
}
違法である場合delete nullptr
、へのすべての呼び出しはdelete
...で囲まれます。
if(ptr)
...そしてそれは不自由でしょう。これが標準であり、本質的に必須の慣習であるため、チェックの必要性を完全に排除しないのはなぜでしょうか? への呼び出しごとに追加の 5 文字 (最小) が必要なのはなぜdelete
ですか?
まず、NULL
(ホストされたC ++プログラムでは)有効なポインター値になることはないため、ポインターがライブオブジェクトを指しているかどうかについてあいまいさはありません。第2に、内部メモリ管理ロジックは、簿記を実行するためにとにかく独自のチェックを実行する必要があるため、ポインタをnull以外にすることを義務付けることからはおそらく何も得られません。
これで、このルールに反対するものは何もないことがわかりました。これが有利な大きな議論です。コードの記述がはるかに簡単になります。この単純な例外処理の割り当てコードについて考えてみます。
T * p1 = NULL;
T * p2 = NULL;
T * p3 = NULL;
try
{
p1 = new T;
p2 = new T;
p3 = new T;
}
catch (...)
{
delete p1;
delete p2;
delete p3;
throw;
}
これはシンプルで整頓されています。どこにでもNULLチェックを追加する必要がある場合、コードが非常に読みにくくなり、コードのロジックがわかりにくくなります。
ライブラリの実装者は一度だけ書く必要があるからif (ptr == nullptr) return;
です。ユーザーであるあなたは、プログラム全体で999999999回書き込む必要があります。したがって、内部でそれを行う方delete
がはるかに簡単であるというのは単純なケースです。
標準委員会は、プログラムが有効なオブジェクトを指すために NULL を持つことができないことを知っているため、つまり、NULL は有効なメモリを指すことができないため、実際には何も削除delete NULL
しないため、安全に書き込むことができます。それは安全なので、前に NULL をチェックする必要がなくなります:delete
//if (ptr != NULL) NOT NEEDED
delete ptr; //safe even if ptr == NULL
ヌル ポインターを削除しても効果はありません (割り当て解除関数が標準ライブラリで提供されている場合[2])。そのため、delete を呼び出す前にヌル ポインターをチェックする必要はありません。
NULL ポインターを削除しても安全ですか?も確認 してください。それはあなたを助けるかもしれません
そうですね、pointer-to- const
(現在は OK) を削除するための規則が標準化に伴って変更されたことをはっきりと覚えています。つまり、ARM の Annotated Reference Manual では異なっていました。
しかし、0を削除するかどうかはわかりません。いつも支えられていると思います。
とにかく、チェックのコストがわずかであり、削除のためにユーザー定義のラッパー関数よりもコンパイラーによって効率的に実行できる可能性がある操作の場合は、ほぼ便利です。