NULLポインターを削除しても安全ですか?


299

NULLポインターを削除しても安全ですか?

そしてそれは良いコーディングスタイルですか?


21
を1回呼び出すことなくC ++プログラムを作成することをお勧めしdeleteます。代わりにRAIIを使用してください。これは、使用されるstd::vector<T> v(100);代わりにT* p = new T[100];、スマートのようなポインタを使用し、unique_ptr<T>そしてshared_ptr<T>その代わりなど生のポインタの削除の世話を
fredoverflow

8
おかげでmake_shared(C ++ 11)とmake_unique(C ++ 14)あなたのプログラムが含まれている必要がありますゼロnewdelete
sp2danny

2
アトミック<T *>のように、新規/削除を必要とするまれなケースがまだある場合があります。アトミック<unique_ptr <T >>は許可されておらず、アトミック<shared_ptr <T >>には、場合によっては許容できないオーバーヘッドがあります。
atb 2015

2
RAIIを使用したリソース管理でクラスを宣言するには、newを呼び出して削除する必要がありますか、またはこれを非表示にするテンプレートクラスがあると言っています。
VinGarcia 2016年

2
@VinGarcia重要な点は、ほとんどのユーザー/クライアント(つまり、非ライブラリ)コードは、newまたはを記述する必要がないということdeleteです。標準コンポーネントでは処理できないリソースを管理するために設計されたクラスは、当然、必要なことを実行できますが、重要なのは、エンドユーザーコードではなく、管理するメモリで醜い処理行うことです。したがって、独自のライブラリ/ヘルパークラスを作成してnew/ を行いdelete、それらの代わりにそのクラスを使用します。
underscore_d

回答:


265

deleteとにかくチェックを実行するので、あなたの側でそれをチェックすると、オーバーヘッドが追加され、醜く見えます。あ非常に良い練習をした後、NULLへのポインタを設定していますdelete(二重欠失および他の同様のメモリ破損の問題回避に役立ちます)。

deleteデフォルトでパラメータをNULLに設定していた場合も好きです

#define my_delete(x) {delete x; x = NULL;}

(私はRとLの値について知っていますが、いいと思いませんか?)


72
削除時にNULLに設定しても、同じオブジェクトを指す他のポインターがいくつか存在する可能性があることに注意してください。
2010年

13
私のコードでは、ほとんどの場合、ポインターは削除されるとスコープ外になります。単にNULLに設定するよりもはるかに安全です。
2010年

142
非常に神の練習をされていない、削除した後、NULLへのポインタを設定します。ポインタを削除した後でNULLに設定すると、メモリ割り当てエラーが発生します。これは非常に悪いことです。正しいプログラムはポインターを2回削除しません。ポインターを2回削除するプログラムクラッシュします。
デイモン

15
@Alice:その点で規格が何を言っているかは無関係です。この規格では、30年前になんらかの理不尽な理由でnullポインターを削除することが有効であると定義されているため、合法です(おそらくCのレガシー)。ただし、同じポインタを(ビットパターンを変更した後でも)2回削除しても、重大なプログラムエラーになります。標準の文言ではなく、プログラムのロジックと所有権によって。nullポインターの削除と同様に、nullポインターはオブジェクトに対応しないためにため、何も削除されない可能性があります。プログラムは、オブジェクトが有効かどうか、誰がオブジェクトを所有しているか、いつ削除できるかを正確に把握している必要があります。
デイモン14年

27
@Damonただし、これらの厳格な所有権ルールのこれらの廃止にもかかわらず、ロックフリー構造は、ロックベースの構造よりもおそらくより堅牢です。そして、はい、私の同僚は、これらの構造体が提供する強化された実行プロファイルと、それらが維持する厳格なスレッドセーフティによって、本当に私を愛しています。ただし、これも暗黙の個人攻撃も、正当性、有効性、所有権の定義とは関係ありません。あなたが提案するものは良い経験則ですが、それは普遍的な法則ではなく、規格に定められているわけでもありません。
アリス

77

C ++ 0xドラフト標準から。

$ 5.3.5 / 2-「[...]どちらの方法でも、deleteのオペランドの値はnullポインター値である可能性があります。[... '」

もちろん、NULL値を持つポインターを「削除」することは決してできませんが、安全に行うことができます。理想的には、NULLポインタの削除を行うコードを含めないでください。しかし、ポインター(コンテナー内など)の削除がループで発生する場合に役立つことがあります。NULLポインタ値の削除は安全であるため、削除するNULLオペランドを明示的にチェックしなくても、削除ロジックを実際に作成できます。

余談ですが、C標準$ 7.20.3.2は、NULLポインターの 'free'は何もしないと言っています。

free関数は、ptrが指すスペースの割り当てを解除します。つまり、追加の割り当てに使用できるようになります。ptrがNULLポインターの場合、アクションは発生しません。


2
最適化されていないコードに非効率性を意図的に導入していなかった場合、その引用に対するこの回答を本当に望みます。受け入れられた回答にあるように、nullポインタの削除は何もしません。したがって、削除する前にポインタがnullかどうかをチェックすることはまったく無関係です。
codetaku 2016年

47

はい、安全です。

nullポインタを削除しても害はありません。割り当てられていないポインタがゼロに初期化され、その後単に削除された場合、関数の末尾でのテストの数を減らすことがよくあります。


前の文は混乱を引き起こしているので、説明されているものの例-これは例外的に安全ではありません-

void somefunc(void)
{
    SomeType *pst = 0;
    AnotherType *pat = 0;

    
    pst = new SomeType;
    
    if (…)
    {
        pat = new AnotherType[10];
        
    }
    if (…)
    {
        code using pat sometimes
    }

    delete[] pat;
    delete pst;
}

サンプルコードで選択できるすべての種類のnitがありますが、概念は(私が望む)明確です。ポインタ変数はゼロに初期化されるのでdelete、関数の最後の操作は、ソースコードでnullでないかどうかをテストする必要がありません。とにかく、ライブラリコードはそのチェックを実行します。


私はそれを理解するために何回か読まなければなりませんでした。メソッドの上部で、またはその最中に、最後ではなく、それらをゼロに初期化することを意味する必要がありますか?それ以外の場合は、ゼロ化と削除の両方を削除するだけです。
ローンの侯爵2014

1
@EJP:関数の完全に信じられないほどの概要は次のようになりますvoid func(void) { X *x1 = 0; Y *y1 = 0; … x1 = new[10] X; … y1 = new[10] Y; … delete[] y1; delete[] x1; }。ブロック構造やジャンプは示していませんがdelete[]、最初の初期化のため、最後の操作は安全です。x1割り当てられた後、割り当てられる前y1に何かがジャンプし、の初期化がなかったy1場合、未定義の動作が発生します。削除前にコードがnullかどうか(x1およびy1)をテストできますが、削除する必要はありません。そう。
ジョナサンレフラー2014

22

nullポインタを削除しても効果はありません。必要がないため、必ずしも良いコーディングスタイルではありませんが、悪くもありません。

優れたコーディング方法を探している場合は、代わりにスマートポインタを使用することを検討してください。そうする必要はまったくありませんdelete


20
NULLポインタを削除したいのは、NULLポインタがNULLを含んでいるかどうかわからないときです... NULLであることを知っていれば、削除を検討していないので、;-)を要求しません。
Tony Delroy、2010年

@トニー:私のポイントは、それが効果がないということだけでした、そしてNULLを時々含むポインタを削除するそのようなコードの存在は必ずしも悪いわけではありません。
ブライアンR.ボンディ2010年

3
IMOの冗長チェックは、パフォーマンス、可読性、保守性の点で確かに悪いものです。
ポール、2014

@paulm OPは確かにそのような悪いこと、Seg Fault / UBのような悪いことについて話していません。


3

削除演算子をオーバーロードしない限り安全です。削除演算子をオーバーロードしてnull条件を処理しないと、安全ではありません。


答えについて説明を追加していただけますか?
MarcinNabiałek2014年

-2

私はそうではないことを経験しましたdelete [] NULL(配列構文など)安全(VS2010)。これがC ++標準に準拠しているかどうかはわかりません。

NULL(スカラー構文)を削除して安全です。


6
これは違法であり、私はそれを信じていません。
Konrad Rudolph

5
nullポインターを削除できるはずです。したがって、それがうまくいかない場合は、おそらくそれを示すコードにバグがあります。
Mysticial 2013

3
§5.3.22番目の代替方法(配列の削除)では、deleteのオペランドの値は、ヌルポインター値、または前の配列new-expressionから生じたポインター値である場合があります
sp2danny 2014

1
@Opux回答で主張されているVS2010の動作。他のコメントで説明されているように、それは安全delete[] NULLです。
Konrad Rudolph

1
@Opuxだから「間違っている」ではなく「信じられない」と書いた。しかし、私はまだしていませんし、それはかなり法外で愚かな標準違反になるでしょう。VC ++は実際には一般に標準の制限に従うのが得意であり、VC ++が違反する場所は歴史的に意味があります。
Konrad Rudolph
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.