2017-09-12 5 views
1

J'apprends le C++ et je veux utiliser des objets dans les classes. La sortie de mon programme me confond, parce que je m'attendais, que le destructeur de données serait appelé deux fois. Mon objet est créé avec "Data data (3);" et son destructeur devrait être appelé à la fin du bloc de code et aussi quand le destructeur de rects est appelé, le destructeur de données à l'intérieur du rect devrait être appelé aussi. Comme je m'y attendais, il imprime "destructeur de données" deux fois après la fin du bloc de code. Mais il l'imprime également, après la création de mon objet de données. Pourquoi cela se produit-il et comment puis-je supprimer correctement la mémoire allouée à l'intérieur des données?Où est appelé le destructeur?

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; 
} 

sortie:

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

Re "Mais il l'imprime aussi, après la création de mon objet de données.", Vous passez un 'Data' par valeur. Cela crée un objet temporaire. Ce qui est détruit. Tout fonctionne comme il se doit, et il n'y a rien à craindre sauf le conseil qui vous a incité à définir une fonction membre 'init'. Ne faites pas cela, et placez la source de ce conseil dans une catégorie «très suspect, doutez de cette personne par défaut». Oh, désolé, je n'ai pas vu: vous ** manque de constructeur de copie **. Cela vous fait «supprimer» un tableau deux fois. Comportement indéfini Utilisez 'std :: vector' à la place! –

+0

@ Cheersandhth.-Alf Les paramètres de fonction ne sont pas des objets temporaires –

+1

Lorsque vous construisez l'objet Rect, vous transmettez la variable 'data' par valeur. Cela va créer une copie de cet objet qui sera détruit après le retour du constructeur Rect. Je pense que c'est celui qui cause la confusion. –

Répondre

0

C'est parce que vous passez la c'tor du Rect une copie des données, qui est détruit après l'appel du constructeur et est donc votre appel desctructor.

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

Vous passez Data en valeur ici, donc un nouveau est créé et détruit lorsque vous appelez cette méthode. Il devrait être:

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

ou peut-être même const Data &data: on ne sait pas pourquoi vous passez un Data quand Rect a déjà un de ses propres. Peut-être vous être copier-hôtel devrait lui attribuer, ou copier-le construire:

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

NB vous avez besoin de la ligne delete data;, en fait comme delete[] data; comme l'a souligné @ P0W. Et le constructeur de copie pour Data::Data(const Data&) ainsi.

+1

L'autre problème est manquant copier-constructeur qui entraîne deux fois la suppression et potentiellement un crash/UB. De plus, la suppression devrait être 'delete [] data;' – P0W