デストラクタでポインタを NULL に設定する価値はありますか? 質問する

デストラクタでポインタを NULL に設定する価値はありますか? 質問する

メモリを割り当てるクラスがあるとします (今のところスマート ポインタについては忘れてください)。

class Foo
{
public:
  Foo() : bar(new Bar)
  {
  }

  ~Foo()
  {
    delete bar;
  }

  void doSomething()
  {
    bar->doSomething();
  }

private:
  Bar* bar;
};

デストラクタ内のオブジェクトを削除するだけでなく、それらを NULL に設定する価値はありますか?

上記の例のデストラクタでポインタを NULL に設定するのは時間の無駄だと思います。

ベストアンサー1

いくつかの回答では、デバッグを支援するために DEBUG ビルドでこれを行う価値があるかもしれないと述べています。

こんなことしないで

実際に顧客に提供するリリース ビルドでは隠されていない問題が、デバッグ ビルドでは隠される可能性があります (これは、デバッグ ビルドが持つべき効果とは逆の効果です)。

dtorのポインタを「クリア」する場合は、別のイディオムの方が良いでしょう。ポインタを既知の不正なポインタ値そうすれば、どこかにオブジェクトへの参照がぶら下がっていて、最終的にポインターを使用しようとする場合、バグのあるコードがポインターが NULL であることに気付いてポインターの使用を避けるのではなく、診断可能なクラッシュが発生します。

たとえば次doSomething()のようになります:

void doSomething()
{
    if (bar) bar->doSomething();
}

次に、を呼び出すbar削除されたオブジェクトへの参照が残っている場合に、 を NULL に設定するとバグを隠すことができます。FooFoo::doSomething()

ポインタのクリーンアップが次のようになっている場合:

~Foo()
{
    delete bar;
    if (DEBUG) bar = (bar_type*)(long_ptr)(0xDEADBEEF);
}

バグを捕まえる可能性が高くなるかもしれません (ただし、放っておいてもbarおそらく同様の効果があります)。

Fooこれで、削除されたオブジェクトへの未解決の参照が何かにある場合、barを使用すると NULL チェックによりその参照が回避されなくなります。ポインターを使用しようとするためクラッシュが発生し、デバッグ ビルドでは何も問題が起きませんが、顧客のリリース ビルドでは未解決の参照が (悪影響で) 引き続き使用されることになります。このクラッシュは修正可能です。

デバッグ モードでコンパイルする場合、デバッグ ヒープ マネージャーが既にこの処理を実行している可能性がかなり高くなります (少なくとも MSVC のデバッグ ランタイム ヒープ マネージャーは、解放されたメモリを 0xDD で上書きして、メモリが使用されていない/解放されていることを示します)。

重要なのは、生のポインターをクラス メンバーとして使用している場合、dtor の実行時にポインターを NULL に設定しないことです。

このルールは他の生のポインタにも適用される可能性がありますが、それはポインタがどのように使用されるかによって異なります。

おすすめ記事