2017-09-12 15 views
1

私はC++を学んでおり、クラスでオブジェクトを使いたいと思っています。私のプログラムの出力は、私が予想していたので、データデストラクタが2回呼び出されることを私に混乱させます。私のオブジェクトは、 "データデータ(3);"コードブロックの最後でデストラクタを呼び出す必要があり、またrectsデストラクタが呼び出されると、rect内のデータのデストラクタも呼び出される必要があります。私が期待したように、コードブロックが終了してから2回、「データデストラクタ」を印刷します。しかし、それはまた、私のデータオブジェクトが作成された後、それを印刷します。なぜこれが起こり、データ内の割り当てられたメモリを正しく削除することができますか?デストラクタはどこにありますか?

class Data { 
private: 
    int* data; 
    int size; 
public: 
    Data() { 
     size = 10; 
     data = new int[size]; 
    } 
    Data(int size) 
     : size(size) { 
     data = new int[size]; 
    } 
    virtual ~Data() { 
     // delete data; 
     std::cout << "data destruktor" << std::endl; 
    } 
    void init(int val) { 
     for (int i = 0; i < size; i++) 
      data[i] = val; 
    } 
    int& operator[](int index) { 
     return data[index]; 
    } 
    int getSize() const { 
     return size; 
    } 
}; 

class Rect { 
private: 
    Data data; 
    int width, height; 
public: 
    Rect() {} 
    Rect(int width, int height, Data data, int val = 0) 
     : width(width), height(height), data(data) { 
     data.init(val); 
    } 
    int getWidth() const { 
     return width; 
    } 
    int getHeight() const { 
     return height; 
    } 
    int getArea() const { 
     return width * height; 
    } 
    Data& getData() { 
     return data; 
    } 
}; 

int main() { 

    { 
     Data data(3); 
     std::cout << "data created" << std::endl; 
     Rect rect(5, 4, data, 9); 
     std::cout << "end of code block" << std::endl; 
    } 

    std::cout << "end of program" << std::endl; 

    system("pause"); 
    return 0; 
} 

出力:

data created 
data destruktor 
end of code block 
data destruktor 
data destruktor 
end of program 
+0

Re "しかし、データオブジェクトが作成された後にも出力されます。"では、値で 'Data'を渡しています。それは一時的なオブジェクトを作成します。それは破壊される。すべてがうまく動くので、 'init'メンバ関数を定義するように誘惑したアドバイス以外は心配する必要はありません。ちょうどそれをしないで、そのアドバイスのソースを「非常に疑わしい、その人の声明がデフォルトでは疑わしい」カテゴリに入れてください。ああ、申し訳ありませんが、私は見ませんでした:コピーコンストラクタがありません**。これにより、配列を2回「削除」できます。未定義の動作。代わりに 'std :: vector'を使用してください! –

+0

@ Cheersandhth.-Alf関数のパラメータは一時オブジェクトではありません –

+1

Rectオブジェクトを構築する際には、値によって 'data'変数を渡しています。これにより、そのオブジェクトのコピーが作成され、Rectコンストラクタからの復帰後に破棄されます。私はそれが混乱を引き起こしていると思います。 –

答えて

0

あなたはコンストラクタの呼び出し後に破壊し、そのため、あなたdesctructor呼び出しでされている、のRectのc'torにデータのコピーを渡しているためです。

0
Rect(int width, int height, Data data, int val = 0) 

現在値によってDataを渡しているので、あなたは、このメソッドを呼び出したときに新しいものが作成され、失われます。それは次のようになります。

Rect(int width, int height, Data &data, int val = 0) 

または可能性もconst Data &dataRectはすでに、独自のものを持っているときにDataを渡している理由は明らかではありません。たぶん、あなたはそれがコピー割り当てること、またはコピー構築し、それをshoudl:

Rect(int width, int height, const Data &data, int val = 0) 
: data(data) 
// ... 

NBの@ P0Wで指摘したようにあなたが実際にdelete[] data;として、delete data;ラインが必要です。 Data::Data(const Data&)のコピーコンストラクタも同様です。

+1

もう1つの問題は、コピーコンストラクタが2回削除され、クラッシュ/ UBが発生する可能性があります。また、deleteは 'delete [] data;でなければなりません。 – P0W

関連する問題