2010-11-21 32 views
6

ベクトルメンバー変数を明示的に消去したい理由(dtor内のonのもの)(以下のコードを参照してください).dtorの最後の行の直後に破棄されるにもかかわらず、コードが実行されます、次のコードについてデストラクタのメンバ変数を無効にする必要がありますか?

class A 
{ 
~A() 
{ 
    values.clear(); 
} 

private: 
    std::vector <double> values_; 
}; 

同様の質問:??

class B 
{ 
~B() 
{ 
    if (NULL != p) 
    { 
     delete p_; 
     p_ = NULL; 
    } 
} 

private: 
    A * p_; 
}; 

をデストラクタが、なぜその後、P_を無効にする、二回呼び出されます

+0

こんにちはマイケル、あなたのタイトルをクリーンアップする必要があります。あなたはそのようにもっと多くの反応を得るでしょう。 –

+1

マイケルFTFY。私の編集が悪いと感じたら、元気に戻してください。 –

答えて

11

に方法はありませんので、クラスAでは、デストラクタのvector型メンバー変数.clear()に絶対に理由はありません。 vectorデストラクタと呼ばれる場合は.clear()vectorとなります。クラスB

、クリーンアップコードは、単にのように書くことができる:

delete p_; 

delete NULL;が無OPはないように定義されているため、p_ != NULL最初かどうかをテストする必要はありません。また、deleteの後にp_ = NULLを設定する必要はありません。なぜなら、それがメンバーであるオブジェクトが破棄された後にp_に正当なアクセスができなくなるからです。

つまり、C++コードではdeleteを使う必要はほとんどありません。リソースの有効期間を自動的に管理するには、Scope-Bound Resource Management(SBRM、Resource Acquisition Is Initializationとも呼ばれます)を使用することをお勧めします。

この場合、スマートポインタを使用できます。 boost::scoped_ptrstd::unique_ptr(C++ 0xより)はどちらも良い選択です。どちらも、生ポインタを使用するのと比べてオーバーヘッドがありません。さらに、暗黙的に宣言されたコピーコンストラクタとコピー代入演算子の生成を抑制します。これは、動的に割り当てられたオブジェクトへのポインタであるメンバ変数を持つときに通常必要となります。

+4

「めったにC++での削除を使用しない」コードを除いて、素晴らしい答えです。私は、auto_ptrやunique_ptrのようなものが多くの状況に注意を払うことに同意します。 "削除"は/めったに/使われてはいけないと言うのは絶対に間違いです。 –

+5

@edA:いいえ、実際はありません。まれに使用するべきではありません。あなたが必要と思う状況を私たちに与えてください。私たちはそれをよりきれいにして安全にします。 **すべての**リソースはラップする必要があるため、ラッパーのみを使用する必要があります。デストラクタ以外の場所に 'delete'がある場合、それは間違っています。 – GManNickG

+5

@edA:私はその声明に従っています。私は過去2年間に新しい生産コードに1つの 'delete'式を書いていませんでした(それ以前は、正しいC++コードを書いたときに完全なnoobでした)。 –

0

p_の場合、デストラクタでnullに設定する必要はありませんが、それは便利な防御メカニズムになります。 Bオブジェクトが削除された後にBオブジェクトへのポインタがまだ残っている場合を想像してみましょう。

Bオブジェクトを削除しようとすると、p_ nullは2番目の削除を無害にしますヒープ破損者。

Bオブジェクトのメソッドを呼び出そうとすると、p_ nullは即座にクラッシュを引き起こします。 p_がまだ古い値である場合、結果は未定義であり、結果のクラッシュの原因を追跡するのは難しいかもしれません。

+0

これは問題ではありません。複数のものが何かを参照している場合、その何かが 'shared_ptr'に置かれていたはずです。問題が解決しました。 – GManNickG

+2

本当にバグがある場合は、ポインタをnullに設定するとバグが隠されます。それは本当にあなたが望むものですか?いいえ、あなたは*恐ろしいほど速くクラッシュすることを望みます。 – fredoverflow

+0

@Fred、そうですが、設定したままにしてもそれは発生しません。二重削除バグを追跡しようとしましたか?彼らは楽しいものではありません。 –

2

第2の例では、p_を無効にする理由はありません。具体的にはデストラクタで行われるため、p_の寿命がその直後に終了することになります。

さらにdelete式はこのチェックを内部的に実行するため、deleteを呼び出す前にp_をnullに比較することはできません。あなたの特定の人工的な例では、デストラクタは単にdelete p_を含み、他に注意する必要があります。いいえif、ヌルに設定すると、p_になりません。

関連する問題