ポインターを削除した後でNULLにすることは良い習慣ですか?


150

まず、スマートポインタを使用することから始めます。これについて心配する必要はありません。

次のコードの問題は何ですか?

Foo * p = new Foo;
// (use p)
delete p;
p = NULL;

これは、別の質問に対する回答とコメントによって刺激されましNeil Butterworthからの1つのコメントで、いくつかの賛成票が生成されました。

削除後にポインターをNULLに設定することは、C ++では普遍的な推奨事項ではありません。これを行うのが良い場合もあれば、無意味でエラーを隠すことができる場合もあります。

それが役に立たない状況はたくさんあります。しかし、私の経験では、害はありません。誰かが私を啓発します。


6
@Andre:技術的には未定義です。発生する可能性が高いのは、以前と同じメモリにアクセスすることですが、別のメモリで使用されている可能性があります。メモリを2回削除すると、プログラムの実行が見つけにくくなる可能性があります。deleteただし、nullポインターを使用しても安全です。これは、ポインターをゼロにすることが有効な理由の1つです。
David Thornley、

5
@AndréPena、それは未定義です。多くの場合、それは再現性さえありません。ポインタをNULLに設定すると、デバッグ時にエラーがより見やすくなり、エラーを繰り返しやすくすることができます。
マークランサム

3
@André:誰にもわかりません。未定義の動作です。アクセス違反でクラッシュしたり、アプリケーションの残りの部分で使用されているメモリを上書きしたりする可能性があります。言語標準は何が起こるかを保証するものではないため、いったん発生したアプリケーションを信頼することはできません。それは可能性が核ミサイルを発射したり、ハードドライブをフォーマットしました。アプリのメモリを破壊したり、悪魔が鼻から飛び出したりする可能性があります。すべての賭けはオフです。
2009

16
空飛ぶ悪魔はバグではなく機能です。
jball 2009

3
他の質問はCについてであり、これはC ++についてであるので、この質問は重複ではありません。答えの多くは、C ++では利用できないスマートポインターなどに依存しています。
エイドリアン・マッカーシー2013年

回答:


86

ポインターを0に設定すると(標準のC ++では「null」であり、CからのNULL定義は多少異なります)、二重削除によるクラッシュを回避できます。

以下を検討してください。

Foo* foo = 0; // Sets the pointer to 0 (C++ NULL)
delete foo; // Won't do anything

一方:

Foo* foo = new Foo();
delete foo; // Deletes the object
delete foo; // Undefined behavior 

つまり、削除済みポインタを0に設定しないと、二重削除を行うと問題が発生します。削除後にポインターを0に設定することに対する反対の議論は、そうすることで二重削除のバグをマスクし、それらを未処理のままにすることです。

明らかに、二重削除バグがないことが最善ですが、所有権のセマンティクスとオブジェクトのライフサイクルによっては、これを実際に達成するのは難しい場合があります。私はUBよりもマスクされた二重削除バグを好む。

最後に、オブジェクトの割り当ての管理に関する補足事項として、ニーズに応じて、std::unique_ptr厳密なstd::shared_ptr所有権または単一の所有権、共有の所有権、または別のスマートポインタの実装を確認することをお勧めします。


13
アプリケーションは、二重削除で常にクラッシュするとは限りません。2つの削除の間に何が起こるかに応じて、何が起こる可能性があります。ほとんどの場合、ヒープが破損し、後で完全に無関係なコードの一部でクラッシュします。通常、segfaultは暗黙的にエラーを無視するよりも優れていますが、この場合、segfaultは保証されておらず、実用性に問題があります。
Adam Rosenfield、

28
ここでの問題は、二重削除があることです。ポインタをNULLにしても、その事実は隠され、修正も安全もされません。1年後に戻ってきて、fooが削除されたのを見るmainainerを想像してみてください。残念ながら、彼はポインターを再利用できると信じていますが、2番目の削除を見逃す可能性があり(同じ関数内にない場合もあります)、2番目の削除によってポインターの再利用が破棄されます。2回目の削除後のアクセスは、大きな問題になっています。
マーティンヨーク

11
ポインタの設定がNULL二重削除のバグを隠すことができるのは事実です。(一部の人はこのマスクを実際に解決策であると見なすかもしれません-それは問題の根本に到達しないので、それは非常に良いものではありません)。削除されたデータにアクセスする際の一般的な問題。
エイドリアン・マッカーシー、

AFAIK、std :: auto_ptrは次のC ++標準で非推奨になりました
rafak '19

私は非難されたとは言いません、それはアイデアがちょうどなくなったように聞こえます。むしろ、移動セマンティクスを使用して、実行しようとしたことを行うに置き換えられてunique_ptrauto_ptrます。
GManNickG '19

55

ポインターが指すものを削除した後でポインターをNULLに設定しても、害はありませんが、多くの場合、より根本的な問題に対するバンドエイドのようです。なぜ最初にポインターを使用しているのですか?2つの典型的な理由がわかります。

  • 単にヒープに何かを割り当てたかっただけです。その場合、それをRAIIオブジェクトでラップするほうがはるかに安全でクリーンになります。オブジェクトが不要になったら、RAIIオブジェクトのスコープを終了します。そうですstd::vectorであり、割り当てを解除されたメモリへのポインタを誤って残してしまう問題を解決します。ポインタはありません。
  • または、複雑な共有所有権のセマンティクスが必要な場合もあります。から返されたポインタは、呼び出されたポインタnewと同じでない場合がありますdelete。その間、複数のオブジェクトが同時にそのオブジェクトを使用した可能性があります。その場合は、共有ポインタまたは同様のものが望ましいでしょう。

私の経験則では、ユーザーコード内にポインターを置いたままにしておくと、間違っていることになります。そもそもポインタがゴミを指すようにしてはいけません。なぜその有効性を保証する責任を負うオブジェクトがないのですか?指摘されたオブジェクトが終了してもスコープが終了しないのはなぜですか?


15
それで、そもそも生のポインタがあったはずがないという主張をしているのです。そして、そのポインタに関係するものはすべて、「良い習慣」という言葉に恵まれるべきではありません。けっこうだ。
マークランサム

7
まあ、多かれ少なかれ。生のポインタを含むものは何も良い習慣とは言えません。それはルールというよりは例外です。通常、ポインタの存在は、より深いレベルで何か問題があることを示しています。
2009

3
しかし、当面の質問に答えるために、いいえ、ポインターをnullに設定するエラーが発生する方法はわかりません。
2009

7
私は同意しません-ポインターを使用すると良い場合があります。たとえば、スタックには2つの変数があり、そのうちの1つを選択したいとします。または、オプションの変数を関数に渡します。私は、と組み合わせて生のポインタを使用してはならないことを言うでしょうnew
rlbond 2009

4
ポインターが範囲外に出たとき、それを処理するために何かまたは誰かがどのように対処する必要があるかわかりません。
2010年

43

さらに良いベストプラクティスがあります。可能であれば、変数のスコープを終了します。

{
    Foo* pFoo = new Foo;
    // use pFoo
    delete pFoo;
}

17
はい、RAIIはあなたの友達です。クラスで包むとさらに簡単になります。または、STLを使用してメモリを自分で処理しないでください。
ブライアン

24
はい、確かに、それが最良の選択肢です。しかし、質問には答えません。
マークランサム

3
これは、関数スコープの期間を使用したことによる副産物のようであり、実際には問題に対処していません。ポインタを使用しているときは、通常、それらのコピーを数層の深さに渡しており、問題に対処しようとしても、メソッドは本当に意味がありません。優れた設計がエラーを特定するのに役立つことに同意しますが、あなたの方法がそのための主要な手段であるとは思いません。
San Jacinto

2
考えてみてください。これができたら、ヒープを忘れてすべてのメモリをスタックから引き出してみませんか?
San Jacinto、

4
私の例は意図的に最小限にしています。たとえば、新しいオブジェクトではなく、オブジェクトがファクトリによって作成されている場合があります。その場合、オブジェクトはスタックに配置できません。または、スコープの最初に作成されたのではなく、何らかの構造に配置されている場合もあります。私が説明しているのは、このアプローチではコンパイル時にポインターの誤用が検出されるのに対し、NULLにすると実行時に誤用が検出されることです。
ドンノイフェルド

31

ポインターを指すオブジェクトを削除した後は、常にポインターをNULL(今はnullptr)に設定します。

  1. これは、解放されたメモリへの多くの参照をキャッチするのに役立ちます(ヌルポインターの逆参照でプラットフォームに障害があると想定)。

  2. たとえば、ポインタのコピーがある場合、解放されたメモリへのすべての参照をキャッチしません。しかし、何よりも優れているものもあります。

  3. それは二重削除をマスクしますが、それらはすでに解放されたメモリへのアクセスよりもはるかに一般的ではありません。

  4. 多くの場合、コンパイラはそれを最適化します。それで、それが不必要であるという主張は私を説得しません。

  5. すでにRAIIを使用している場合deleteは、最初からコードにが多くないため、追加の割り当てによって混乱が生じるという議論は私を説得しません。

  6. デバッグ時に、古いポインタではなくnull値を確認すると便利なことがよくあります。

  7. それでも問題が解決しない場合は、代わりにスマートポインタまたは参照を使用してください。

また、リソースが解放されたときに他のタイプのリソースハンドルをno-resource値に設定します(これは通常、リソースをカプセル化するために作成されたRAIIラッパーのデストラクタでのみです)。

大規模な(900万ステートメント)商用製品(主にC)に取り組みました。ある時点で、メモリが解放されたときにマクロマジックを使用してポインターをnullにしました。これにより、すぐに修正された多くの潜んでいるバグがすぐに明らかになりました。私が覚えている限り、ダブルフリーのバグはありませんでした。

更新:マイクロソフトは、これはセキュリティにとって良い習慣であると信じており、SDLポリシーでの実践を推奨しています。どうやら、MSVC ++ 11は、/ SDLオプションを指定してコンパイルすると、削除されたポインタを(多くの状況で)自動的に踏みつけます。


12

まず、このトピックや密接に関連するトピックについては、既存の質問がたくさんあります。たとえば、削除を行わないとポインタがNULLに設定されないのはなぜですか。

あなたのコードでは、何が起こっているのかという問題(pを使用)。たとえば、次のようなコードがあるとします。

Foo * p2 = p;

次に、心配するポインタp2が残っているため、pをNULLに設定してもほとんど効果がありません。

これは、ポインタをNULLに設定しても常に無意味であると言っているのではありません。たとえば、pが、存続期間がpを含むクラスとまったく同じではないリソースを指すメンバー変数である場合、pをNULLに設定することは、リソースの有無を示すのに役立つ方法です。


1
それが役に立たない場合があることにも同意しますが、あなたはそれが積極的に有害である可能性があることを示唆しているようでした。それはあなたの意図ですか、それとも私はそれを間違って読みましたか?
マークランサム

1
ポインタのコピーが存在するかどうかは、ポインタ変数をNULLに設定する必要があるかどうかという問題には関係ありません。NULLに設定することは、夕食後の食器洗浄と同じ理由で良い習慣です。これは、コードが持つ可能性のあるすべてのバグに対する安全策ではありませんが、コードの正常性を促進します。
Franci Penov 2009

2
@Franci多くの人があなたに反対しているようです。また、オリジナルを削除した後でコピーを使用しようとする場合は、コピーがあるかどうかが重要です。

3
フランシ、違いがあります。あなたはそれらを再び使用するので、あなたは皿をきれいにします。削除したポインタは必要ありません。それはあなたがする最後のことでなければなりません。ベターの練習は完全に事態を避けるためです。
GManNickG 2009

1
変数を再利用できますが、防御的プログラミングの場合ではなくなります。それは、目の前の問題の解決策を設計した方法です。OPは、この防御的なスタイルが私たちが努力すべきものであるかどうかについて議論しており、ポインターをnullに設定することはありません。そして理想的には、あなたの質問に、はい!ポインターを削除した後は使用しないでください。
GManNickG

7

の後にさらにコードがある場合delete、はい。コンストラクターで、またはメソッドや関数の最後でポインターが削除された場合、No。

このたとえの要点は、実行時に、オブジェクトがすでに削除されていることをプログラマに思い出させることです。

さらに良い方法は、ターゲットオブジェクトを自動的に削除するスマートポインタ(共有またはスコープ)を使用することです。


全員(元の質問者を含む)は、スマートポインターを使用する方法に同意しています。コードは進化します。最初に削除した後、削除後にコードがなくなる可能性がありますが、時間の経過とともに変更される可能性があります。割り当てを行うと、それが発生したときに役立ちます(その間、コストはほとんどかかりません)。
Adrian McCarthy

3

他の人が言ったように、delete ptr; ptr = 0;悪魔があなたの鼻から飛び出すことはありません。ただし、ptr一種のフラグとしての使用を奨励します。コードは散らかってdelete、ポインタをに設定しますNULL。次のステップはif (arg == NULL) return;NULLポインターを誤って使用しないようにするために、コードを分散させることです。問題は、チェックがNULLオブジェクトまたはプログラムの状態をチェックする主要な手段になると発生します。

どこかでポインタをフラグとして使用することについてコードのにおいがあると確信していますが、見つかりません。


9
フラグとしてポインターを使用することに問題はありません。ポインタを使用してNULLいて、それが有効な値でない場合は、おそらく代わりに参照を使用する必要があります。
エイドリアン・マッカーシー、

2

質問を少し変更します。

初期化されていないポインタを使用しますか?NULLに設定していない、またはNULLが指すメモリを割り当てていないものですか。

ポインターをNULLに設定することをスキップできるシナリオは2つあります。

  • ポインタ変数はすぐにスコープ外になります
  • ポインタのセマンティクスをオーバーロードし、その値をメモリポインタとしてだけでなく、キーまたは生の値としても使用しています。ただし、このアプローチには他の問題があります。

一方、ポインターをNULLに設定するとエラーが隠される可能性があると主張すると、修正によって別のバグが隠される可能性があるため、バグを修正すべきではないと主張するように聞こえます。ポインターがNULLに設定されていない場合に表示される可能性がある唯一のバグは、ポインターを使用しようとするバグです。しかし、これをNULLに設定すると、解放されたメモリで使用した場合とまったく同じバグが発生しますね。


(A)「バグを修正してはならないと主張するような音」ポインターをNULLに設定しないことはバグではありません。(B)「しかし、これをNULLに設定すると、実際にはまったく同じバグが発生します」いいえ。NULLに設定すると、二重削除が非表示になります。(C)概要:NULLに設定すると、二重削除が非表示になりますが、古い参照が公開されます。NULLに設定しないと、古い参照を非表示にすることができますが、二重削除が発生します。双方は、本当の問題は古い参照と二重削除を修正することであることに同意します。
Mooing Duck 2013

2

ポインターを削除した後でNULLに設定するかしないかを強制する他の制約がない場合(そのような制約の1つはNeil Butterworthによって言及されました)、私の個人的な好みはそのままにすることです。

私にとっての質問は、「これは良いアイデアですか?」ではありません。しかし、「これを行うことによって、どのような行動を防止または成功させることができますか?」たとえば、これにより他のコードがポインターが使用できなくなったことを確認できる場合、他のコードが解放された後に解放されたポインターを調べようとするのはなぜですか?通常、これはバグです。

また、必要以上に多くの作業を行い、事後デバッグを妨げます。不要になった後にメモリに触れる回数が少ないほど、何かがクラッシュした理由を簡単に理解できます。多くの場合、メモリは特定のバグが発生したときと同じ状態にあり、そのバグを診断して修正するという事実に依存してきました。


2

削除後の明示的なnullは、ポインタが概念的にオプションである何かを表すことを読者に強く示唆しています。それが行われているのを見た場合、ソース内のすべての場所でポインタが使用され、最初にNULLに対してテストする必要があるのではないかと心配し始めます。

それが実際の意味である場合は、boost :: optionalのようなものを使用して、ソースで明示的にすることをお勧めします。

optional<Foo*> p (new Foo);
// (use p.get(), but must test p for truth first!...)
delete p.get();
p = optional<Foo*>();

しかし、ポインタが「悪くなった」ことを人々に本当に知りたいのであれば、私は、最善の方法はそれを範囲外にすることだと言う人々と100%同意するつもりです。次に、コンパイラーを使用して、実行時の不正な逆参照の可能性を防ぎます。

それはすべてのC ++浴槽の中の赤ん坊です。それを捨ててはいけません。:)


2

適切なエラーチェックを備えた適切に構造化されたプログラムでは、nullを割り当てない理由はありません0この文脈で広く認識されている無効な値として単独で存在します。ハードに失敗し、すぐに失敗します。

割り当てに対する反対意見の多くは、バグを隠したり、制御フローを複雑にしたりする可能性が0あることを示唆しています。基本的に、それは上流のエラー(あなたのせいではなく(悪い駄洒落ではなく))またはプログラマーのための別のエラーです-おそらくプログラムの流れが複雑になりすぎたという兆候ですらあります。

プログラマーが特殊な値としてnullの可能性があるポインターの使用を導入し、その周りに必要なすべての回避を記述したい場合、それは彼らが故意に導入した複雑さです。隔離が適切であればあるほど、誤用のケースが早く発見され、他のプログラムに拡散することが少なくなります。

これらのケースを回避するために、C ++機能を使用して、適切に構造化されたプログラムを設計できます。参照を使用することも、「nullまたは無効な引数を渡す/使用することはエラーである」と言うこともできます。これは、スマートポインタなどのコンテナにも同様に適用できるアプローチです。一貫性のある正しい動作を増やすと、これらのバグが遠ざかることを禁じます。

そこからは、nullポインターが存在する(または許可される)可能性のあるスコープとコンテキストが非常に限定されます。

同じでないポインタにも適用できconstます。ポインタの値をたどることは、そのスコープが非常に小さく、不適切な使用がチェックされ、明確に定義されているため、簡単です。ツールセットとエンジニアが簡単な読み取りでプログラムを追跡できない場合、または不適切なエラーチェックや一貫性のない/緩やかなプログラムフローがある場合は、他に大きな問題があります。

最後に、コンパイラと環境には、エラー(落書き)を導入したり、解放されたメモリへのアクセスを検出したり、他の関連するUBをキャッチしたりするときに、ガード機能が備わっている可能性があります。多くの場合、既存のプログラムに影響を与えることなく、同様の診断をプログラムに導入することもできます。


1

質問にすでに入力した内容を拡張してみましょう。

箇条書きの形式で、質問に入力した内容は次のとおりです。


削除後にポインターをNULLに設定することは、C ++では普遍的な推奨事項ではありません。以下の場合があります。

  • それは良いことです
  • そしてそれが無意味でエラーを隠すことができる時。

しかし、これが悪いことはありません!あなたがなりません明示的にゼロにすることによってより多くのバグを紹介し、あなたはありません漏れるメモリを、あなたはありません未定義の動作が原因発生します。

したがって、疑わしい場合は、無効にします。

そうは言っても、いくつかのポインターを明示的にnullにする必要があると感じた場合は、メソッドを十分に分割していないように思えます。メソッドを分割するための「抽出メソッド」と呼ばれるリファクタリングアプローチを検討する必要があります。別パーツ。


「これが悪いことはありません」には同意しません。このイディオムがもたらすカッターの量を考慮してください。あなたは何かを削除し、すべてのユニットに含まれているヘッダーを持っており、これらすべての削除場所はなってわずかに少ないストレートフォワード。
GManNickG 09

悪い時があります。削除されたはずのnullポインターが不要な場合に誰かが逆参照しようとすると、おそらくクラッシュせず、そのバグは「非表示」になります。ランダムな値が残っている削除済みポインターを逆参照すると、気付く可能性が高く、バグが見やすくなります。
カーソンマイヤーズ

@Carson:私の経験はまったく逆です。nullptrを逆参照すると、ほとんどすべての方法でアプリケーションがクラッシュし、デバッガーによってキャッチされる可能性があります。ぶら下がりポインタを逆参照しても、通常はすぐに問題は発生しませんが、多くの場合、誤った結果やその他のエラーが発生する可能性があります。
MikeMB 2016年

@MikeMB私は完全に同意します。これについての私の見解は過去〜6.5年で大幅に変化しました
カーソンマイヤーズ

プログラマーという点では、6〜7年前はだれもが別の人でした:)今日はC / C ++の質問に答えるつもりでしたかどうかさえわかりません:)
Lasse V. Karlsen

1

はい。

それができる唯一の「害」は、プログラムに非効率性(不必要なストア操作)を導入することです-しかし、このオーバーヘッドは、ほとんどの場合、メモリブロックの割り当てと解放のコストとの関係では重要ではありません。

あなたがそれをしない場合は、します一日いくつかの厄介なポインタderefernceのバグを持っています。

削除には常にマクロを使用します。

#define SAFEDELETE(ptr) { delete(ptr); ptr = NULL; }

(配列と同様、free()、ハンドルの解放)

呼び出しコードのポインタへの参照を取得する「自己削除」メソッドを記述して、呼び出しコードのポインタを強制的にNULLにすることもできます。たとえば、多くのオブジェクトのサブツリーを削除するには:

static void TreeItem::DeleteSubtree(TreeItem *&rootObject)
{
    if (rootObject == NULL)
        return;

    rootObject->UnlinkFromParent();

    for (int i = 0; i < numChildren)
       DeleteSubtree(rootObject->child[i]);

    delete rootObject;
    rootObject = NULL;
}

編集する

はい、これらのテクニックはマクロの使用に関するいくつかのルールに違反します(そして、はい、最近ではおそらくテンプレートで同じ結果を得ることができます)-しかし、何年にわたって私がデッドメモリにアクセスしたことはありません -最も厄介で最も難しいものの1つ直面する可能性のある問題のデバッグに最も時間がかかる。実際、長年にわたって、私が導入したすべてのチームから、whjoleクラスのバグを効果的に排除してきました。

上記を実装する方法はたくさんあります。私は、呼び出し側のポインターをNULLにしないメモリを解放する手段を提供するのではなく、オブジェクトを削除した場合に、ユーザーにポインターをNULLにするように強制するというアイデアを説明しようとしています。 。

もちろん、上記の例は自動ポインタへのステップにすぎません。これは、OPが自動ポインターを使用しない場合について具体的に要求していたため、提案しませんでした。


2
マクロは、特に通常の関数のように見える場合、悪い考えです。これを行う場合は、テンプレート関数を使用します。

2
うわー...私はポインターをanObject->Delete(anObject)無効にするようなものを見たことがありませんanObject。それはただ恐ろしいことです。このための静的メソッドを作成して、TreeItem::Delete(anObject)最低限強制する必要があります。
D.Shawley、2009

申し訳ありませんが、適切な大文字の「これはマクロです」形式を使用するのではなく、関数として入力しました。修正。自分をよりよく説明するコメントも追加しました。
Jason Williams、

そして、あなたが正しい、私のすぐに打ちのめされた例はゴミでした!修繕 :-)。私は単にこのアイデアを説明する簡単な例を考えようとしていました。他の誰か(呼び出し元)がそのポインターを所有している場合でも、ポインターを削除するコードは、ポインターがNULLに設定されるようにする必要があります。したがって、削除の時点でNULLに強制できるように、常にポインタへの参照を渡します。
Jason Williams、

1

「それを行うのが良いこともあれば、無意味でエラーを隠すことができる場合もあります。」

私は2つの問題を見ることができます:その単純なコード:

delete myObj;
myobj = 0

マルチスレッド環境でfor-linerになります。

lock(myObjMutex); 
delete myObj;
myobj = 0
unlock(myObjMutex);

ドンノイフェルトの「ベストプラクティス」は常に当てはまるとは限りません。たとえば、ある自動車プロジェクトでは、デストラクタでもポインタを0に設定する必要がありました。安全性が重要なソフトウェアでは、このようなルールは珍しくありません。コードでポインターを使用するたびにteam / code-checkerを説得するよりも(そして賢明に)それらをたどる方が簡単です。このポインターをnullにする行は冗長です。

もう1つの危険は、例外を使用するコードでこの手法に依存することです。

try{  
   delete myObj; //exception in destructor
   myObj=0
}
catch
{
   //myObj=0; <- possibly resource-leak
}

if (myObj)
  // use myObj <--undefined behaviour

このようなコードでは、リソースリークを生成して問題を延期するか、プロセスがクラッシュします。

したがって、この2つの問題が頭の中で自然に発生するため(Herb Sutterがもっと詳しく教えてくれます)、「スマートポインターの使用を避けて、通常のポインターで安全にジョブを実行する方法」という質問はすべて廃止されました。


私は、4ライナーが3ライナーよりもはるかに複雑であること(とにかくlock_guardsを使用する必要があります)を確認できず、デストラクタがスローすると、とにかく問題が発生します。
MikeMB

私がこの答えを初めて見たとき、なぜデストラクタでポインタをnullにしたいのか理解していませんでしたが、今はそうです-オブジェクトを所有している場合のためですポインタをするが削除された後に使用されるです!
Mark Ransom

0

心配するダングリングポインタは常に存在します。


1
「これ」の代わりに「ぶら下がりポインタ」を置くのはとても難しいでしょうか?:)少なくともそれはあなたの答えにいくつかの物質を与えます。
GManNickG

4
W3C QAのヒント、「リンクテキストとして「ここをクリック」を使用しないでください」の主題でもあります。w3.org
Tips

0

ポインタを再度使用する前に再割り当てする場合(逆参照、関数への引き渡しなど)、ポインタをNULLにすることは単なる追加の操作です。ただし、再度使用する前に再割り当てされるかどうかわからない場合は、NULLに設定することをお勧めします。

多くの人が言ったように、もちろんスマートポインタを使用する方がはるかに簡単です。

編集:トーマスマシューズがこの以前の回答で述べたように、デストラクタでポインターが削除された場合、オブジェクトが既に破棄されているため、再度使用されることはないため、ポインターをNULLに割り当てる必要はありません。


0

ポインターを削除した後でNULLに設定すると、単一の関数(またはオブジェクト)でそれを再利用する正当なシナリオがあるまれなケースで役立ちます。それ以外の場合は意味がありません-ポインタは、存在する限り意味のある何かを指す必要があります-期間。


0

コードがアプリケーションの最もパフォーマンスが重要な部分に属していない場合は、コードをシンプルに保ち、shared_ptrを使用します。

shared_ptr<Foo> p(new Foo);
//No more need to call delete

参照カウントを実行し、スレッドセーフです。これはtr1(std :: tr1名前空間、#include <memory>)で見つけることができます。コンパイラーが提供していない場合は、boostから取得します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.