2009-04-01 7 views
108

の後にNULLへのポインタの自動設定がの場合、私は常に疑問に思っていました。これが処理されると、無効なポインタによる多くのクラッシュは発生しません。なぜNULLを指すポインタを削除しないのですか?

  1. パフォーマンス:

    追加の命令がdeleteパフォーマンスが低下する可能性がしかし、私は標準がこれを制限していた理由のカップルの考えることができると述べました。

  2. ポインタがconstである可能性があります。

    また、私はこの特殊なケースのために何かをしていた可能性があります。

誰もがこれを許可していないため、正確な理由は知っていますか?

答えて

138

Stroustrup himself答えです。抜粋:

C++が明示的に に左辺値オペランドをゼロにするには、DELETEの 実装を可能にし、私は実装が 、ということをするでしょう を期待していたが、そのアイデアがで人気となっ 持っていないようです実装者。

しかし、彼が提起する主な問題は、deleteの引数が左辺値である必要はないということです。

12

本当に必要がないし、単にポインタではなくポインタへのポインタを削除する必要があるためです。

+1

またはポインタを参照してください。 –

+0

真実ですが、同じオーバーヘッドになります – snemarch

5

ポインタの配列があり、2番目の操作で空の配列を削除する場合は、メモリが解放されようとしているときに各値をnullに設定する必要はありません。それをnullにするにはnullを書きます:)

54

まず、nullに設定するには、メモリに格納された変数が必要です。実際には、変数内にポインタを置いていることがありますが、には、ちょうど計算されたアドレスにあるオブジェクトを削除することがあります。削除を無効にすることは不可能です。

次にパフォーマンスが向上します。 の削除が終了した直後に、ポインタが範囲外になるようなコードを記述している可能性があります。それをヌルで埋めることはちょうど時間の無駄です。そして、C++は "それを必要としない?あなたはそれを支払う必要はありません"というイデオロギーの言葉です。

安全が必要な場合は、サービスの幅広いスマートポインタがあります。よりスマートなポインタを書くこともできます。

+4

良い点wrt計算されたアドレス。何も表示されない場合もあります。 – snemarch

+0

あなたは時にはちょうど計算されたアドレス。 ??? – Destructor

+0

@PravasiMeetいいえ、私は 'delete(ptr + i)'のようなものです – sharptooth

35

そのメモリを指す複数のポインタを持つことができます。削除用に指定したポインタがnullに設定されているにも関わらず、他のすべてのポインタがNULLに設定されていないと、誤った安全感が発生します。ポインタは、アドレス、数値以外何もありません。間接参照操作を持つintでもかまいません。私の主張は、あなたが削除したのと同じメモリを参照しているものを見つけるためにすべての単一ポインタをスキャンしなければならないということです。計算上、そのアドレスのすべてのポインタをスキャンして、それらをヌルにするのは、言語がそのために設計されていないためです。 (他の言語でも同様の目標を達成するために参照を構造化していますが)。

17

ポインタを複数の変数に保存できます。これらのうちの1つをNULLに設定すると、残りの変数に無効なポインタが残ります。だからあなたは本当にあまり得られません、あなたはセキュリティの誤った感覚を作成する可能性が高いです。

ことのほかに、あなたが欲しいものを行い、独自の機能を作成することができます。

template<typename T> 
void deleten(T *&ptr) { 
    delete ptr; 
    ptr = NULL; 
} 
4

C++をあなた自身のオペレータ新しいを定義し、インスタンスのために、彼らはあなた自身のプールアロケータを使用するように削除することができます。これを行うと、厳密にアドレスではなく、プール配列のインデックスと呼ばれるもので、newとdeleteを使用することができます。この文脈では、NULL(0)の値は正当な意味を持つかもしれない(プールの最初の項目を参照する)。
その引数に自動的にNULLを設定すると、必ずしも意味がありません - 値を無効な値に設定してください。無効な値は必ずしもNULLであるとは限りません。

3

ポインターをNULLに自動的に設定しても、ポインターの不適切な使用に関する問題のほとんどは解決されません。回避する唯一のクラッシュは、2回削除しようとする場合です。そのようなポインタでメンバ関数を呼び出すとどうなりますか?それはまだクラッシュします(メンバー変数にアクセスすると仮定して)。 C++は、NULLポインタ上の関数を呼び出すことを制限するものではなく、パフォーマンスの観点から関数を呼び出す必要もありません。

4

C++の哲学は、「あなたがそれを使用する場合にのみそれを支払う」ことです。私はあなたの質問に答えるかもしれないと思います。

また、時には、削除されたメモリを回復する独自のヒープを持つこともできます。また、ポインタはいくつかの変数に格納されています。
ご覧のとおり、多くの問題と考えられる問題があります。

7

deleteは、ほとんどがデストラクタで使用されます。この場合、メンバをNULLに設定するのは無意味です。数行後、閉鎖}で、メンバーは存在しなくなりました。代入演算子では、通常、削除の後に代入が続きます。

また、それは違法以下のコードをレンダリングします:ここで

T* const foo = new T; 
delete foo; 
4

は別の理由です。削除が引数をNULLに設定したとします。

int *foo = new int; 
int *bar = foo; 
delete foo; 

NULLに設定する必要がありますか?これを一般化できますか?

-2

私は、この質問に奇妙な答えを与える人を見ています。

ptr = NULL; このような単純な文は、どのようにしてパフォーマンスの遅延を引き起こしますか?

もう1つの答えは、同じ メモリロケーションを指す複数のポインタを持つことができるということです。確かにできる。この場合、1つのポインタに対する削除操作はそのポインタだけをNULLにし(削除がポインタNULLを作成していた場合)、もう一方のポインタはNULLでなく、空きのメモリ位置を指します。

解決策は、同じ場所を指すポインタをすべて削除する必要があったはずです。内部的には、メモリがすでに解放されていないかどうかをチェックする必要があります。ポインタをNULLにします。

Stroustrupはこのように動作するように設計されている可能性があります。彼はプログラマーがこれを世話すると思った。だから彼は無視した。

関連する問題