2013-05-02 8 views
9

したがって、次の例では、クラスFoo*this = Foo()に置き換えます。私はこの状況で判明したので、私はちょうどこれをテストしてうれしいです。古いFooのデストラクタは呼び出されません。基本的な代入演算子は単にmemcpyを使用するためだと思います...しかし、言語設計の質問として...なぜあなたはデフォルトの代入演算子を代入してオブジェクトを破棄して、事故を防ぐのですか?なぜデフォルトの代入演算子がデストラクタを最初に呼び出さないのですか?

http://codepad.org/9WCo6yZ5

#include <iostream> 
using namespace std; 

class MustBeDestroyed //(for some reason not shown here) 
{ 
public: 
    int i; 
    MustBeDestroyed(int i) : i(i) {} 
    ~MustBeDestroyed() { cout << "destroyed contained class " << i << endl; } 
}; 

class Foo 
{ 
public: 
    MustBeDestroyed x; 
    Foo(int y) : x(y) {} 
    void replace_myself(int y) { Foo f(y); *this=f; } 
    void print() { cout << "This is outer/inner class " << x.i << endl; } 
    ~Foo() { cout << "destroyed outer class " << x.i << endl; } 
}; 

int main() 
{ 
    Foo a(1); 
    a.print(); 
    a.replace_myself(2); 
    a.print(); 
    return 0; 
} 
+2

どのような事故ですか?代入はそれだけです - 新しい値を古い値に代入します。 –

+1

デフォルトの代入演算子はmemcpyを使用しません(ただし、コンパイラの最適化によってその結果になる可能性があります)。メンバーワイズ割り当てです。 – huskerchad

+1

'int i、j; i = 5; j = i; '私はもはや私が使用できないことを期待するのは賢明だと言っていますか?同意しません。 – Fiktik

答えて

1

のルールに違反しましたか?それはまさにそれが言っていることをします:それは代入演算子を呼び出します。コンパイラによって生成された代入演算子は、古いオブジェクトから新しいオブジェクトへのすべてのメンバーの割り当て(割り当て操作を使用して)を明示的に行います。それ以上のものはありません。これはまさに有名なrule of threeの理由です。

なぜ、デストラクターを呼び出さないのか:オブジェクトの有効期間が終了します。理論的には古いオブジェクトの代わりに新しいオブジェクトを構築する可能性がありますが、そのアプローチは通常例外(look at this question for more about that)でも正しくありませんので、一般的なケースでは使用できません。あなたが提案したアプローチを行った場合は、メンバーの代入演算子を呼び出すのではなく、代わりにデストラクタ/コピーコンストラクタを呼び出すことになります。つまり、カスタム割り当ての動作(実際にはコピーの動作と同じである必要はありません)は尊重されません。

+1

上書きされた値にヒープからのデータへのptrが含まれていた場合、割り当ては最初にメモリリークを避けるためにデストラクタを呼び出します。単純にptrを上書きすると、メモリがリークします。したがって、組み込みの代入演算子は、この場合はオーバーライドする必要があります(組み込み関数が漏れるため)。 – wcochran

6

最初のオブジェクトを破壊することは寿命を終えることになるので。次に、新しいオブジェクトの生存期間を開始するためにコンストラクタを呼び出さなければなりません。しかし、演算子=の動作は、現在のオブジェクトを破壊して別のオブジェクトを作成するのではなく、既存のオブジェクトに新しい値を割り当てることです。

基本的に、あなたはなぜ割り当てがデストラクタを呼び出します。3.

関連する問題