0

私のプログラミングのバックグラウンドはJavaの世界ですが、C++の学習を始めたばかりです。私はこのかなり些細でおそらくかなりお粗末な問題に出くわしました。それはどういうわけかJavaプログラマーとして私を困惑させます。

コンストラクタでnewを介して初期化され、デストラクタで削除される配列を持つクラスがあります。このクラスのオブジェクトを作成し、このクラスの別のオブジェクトを同じ変数に割り当てると(少なくともそれは私が思うことです)、変数が離れるときにデストラクタのdelete[]メソッドが2回呼び出されるようです。スコープ(この場合はmain()関数)(デバッガーは_BLOCK_TYPE_IS_VALIDアサーション失敗の警告を表示します)。

何故ですか?新しいオブジェクトをfに割り当てる前に、デコンストラクタが呼び出されないのはなぜですか?Foo(1)を明示的に削除するにはどうすればよいですか?ここで正確に何が起こりますか?

class Foo{
    private:
        int *field;

    public:

    Foo(int size){
       field = new int[size];
    }

   ~Foo(){
       delete[] field;
    }
};


int main(){
    Foo f = Foo(1);
    f = Foo(2);
}
4

2 に答える 2

6

C++ の世界にはRule Of Threeと呼ばれるものがあります。

クラスは、デストラクタコピー コンストラクタ、および代入演算子を自動的に生成します。

これらの関数の 1 つを手動で定義する必要がある場合は、おそらく 3 つすべてを定義する必要があります。

あなたの場合、 のコピーFooが の独自のコピーを取得するように、2 つのコピー関数を定義する必要がありますfield。次の 2 つの関数を追加します。

class Foo{

    Foo( const Foo &f ) {
        size = f.size;
        field = new int[size]; 
        std::copy( f.field, f.field + size, field );
    }

   Foo& operator=( const Foo &f ) {
       // Leverage the logic that was already written in the copy constructor
       Foo tmp(f);
       std::swap( *this, temp );
       return *this;
   }
};

オブジェクトに格納sizeしたと仮定していることに注意してください。Fooとにかく実際のアプリケーションでその情報を保存する必要があるでしょう

于 2013-03-18T23:37:14.873 に答える
2

あなたは 3 つのルールに従っていません。これは悪いことです。デフォルトのコピー コンストラクターは浅いコピーを行うため、すべての自動変数 (fおよび一時変数)fieldには同じ を指すメンバーがintあり、デストラクタが呼び出されると複数回破棄されます。

適切なコピー コンストラクターを実装するか、C++ のイディオムを使用して手動管理を完全に回避します。つまり、std::vector代わりに a を使用します。

于 2013-03-18T23:38:11.523 に答える