problème destructor
-
22-08-2019 - |
Question
est ma fonction addCard qui prend une carte à jouer en tant que paramètre puis mains sur l'adresse de son auto à un tableau attribué de pointeurs vers des objets carte à jouer.
void cardHand::addCard(playingCard card) {
theHand[nElems++] = &card;
} // addCard()
maintenant, quand je lance mon programme, il fonctionne très bien mais tombe en panne lorsque le destructeur.
cardHand::~cardHand() {
for(int c = 0;c<MAX;c++) {
if(theHand[c] != NULL)
delete theHand[c]; // here is the problem
}
delete [] theHand;
} // class destructor
est-ce plantage parce que je suis seulement la remise de l'adresse de l'objet dans la fonction carte à jouer addCard. devrait-il être un pointeur à la place?
La solution
Le problème est ici
void cardHand::addCard(playingCard card) { theHand[nElems++] = &card; }
Vous pouvez stocker l'adresse de l'objet carte temporaire qui sera détruite à la fin de la méthode addCard.
Et dans votre destructor vous essayez de le supprimer à nouveau.
Vous avez deux options.
Première :. AddCard faire accepter simplement la configuration de la carte et créez votre carte avec new
dans la méthode addCard
Deuxième : accepter la carte par pointeur mais la destructor de votre cardHand ne peut pas être responsable de la suppression de la carte. Et la suppression interprétera objet de plate-forme qui a créé toutes les cartes.
Autres conseils
Quand vous dites:
theHand[nElems++] = &card;
Vous mémoriser l'adresse d'un paramètre de fonction, qui est effectivement une variable locale. C'est toujours une mauvaise chose à faire, et dans votre cas provoque l'accident lorsque vous essayez de le supprimer.
Vous voulez probablement quelque chose comme:
theHand[nElems++] = new playingcCard( card );
mais la vraie solution est d'utiliser un std :: vecteur et carte à jouer en finir avec l'allocation dynamique tout à fait.
Vous utilisez C ++ comme un meilleur C, et bien que cela soit bien à de nombreuses fins, il n'est pas idiomatiques C ++.
Qu'est-ce que vous voulez vraiment est de supprimer l'allocation dynamique tout à fait. En général, si vous écrivez C ++, vous devez utiliser très rarement new
et utiliser encore plus rarement delete
.
Votre main doit être déclaré quelque chose comme ceci:
std::vector< playingCard > hand;
Les nouvelles cartes devraient être mis dessus avec quelque chose comme ceci:
hand.push_back( card );
Vous devriez trouver que, en utilisant les classes de collection de la bibliothèque C ++ (et les smart TR1 pointes) vous ne devez jamais utiliser new
ou delete
-. Jusqu'à ce que vous arriviez à écrire vos propres pointeurs intelligents de toute façon
Alors, étant donné les autres réponses, ma façon de le faire serait la main sur une référence ou un pointeur vers un playingCard
.
Et en ce qui concerne delete
, la règle générale est, vous ne delete
ce que vous new
ed, à savoir celui qui alloue la mémoire doit être responsable de son disposale.
Bien sûr, comme toute règle, il y a des exceptions à cela, mais ce comportement doit être très bien documenté dans le contrat d'une interface.
Il se bloque sur delete
parce qu'il n'a jamais été attribué à new
.
void cardHand::addCard(playingCard card) {
theHand[nElems++] = &card;
} // addCard()
Dans cet appel de fonction, vous passez une copie temporaire de la carte à jouer et de prendre son adresse. Le stockage des adresses de est un non temporaires, pas à moins que vous savez vraiment ce que vous faites.
Au lieu de cela, changer cela à quelque chose comme
/** @param card card to add. Takes ownership. */
void cardHand::addCard(playingCard *card) {
theHand[nElems++] = card;
} // addCard()
Et dans le code d'appel, passer un pointeur d'objet playingCard
retour de new playingCard
.
Il a encore la question du transfert de propriété d'objet une raison commune pour le double supprimer des bugs ou des fuites de mémoire. Il est une bonne habitude de faire de tels transferts explicites avec des commentaires de code.
Règle de base: Ne supprimez ce que vous avez alloué (soit avec une nouvelle ou avec malloc)
Par conséquent, votre accident.
La raison pour laquelle il ne fonctionne pas est que vous passez votre classe par valeur cardHand::addCard
.
Alors, que le compilateur n'est construit une copie temporaire de votre instance de classe sur la pile.
Comme il est sur la pile, il se nettoyer automatiquement une fois le retour de la fonction addCard
.
Vous pouvez corriger cela en passant votre instance playingCard
comme pointeur à la place.
Cependant, comme d'autres dans ce poste ont dit, il est conseillé de ne pas delete
choses que vous ne l'avez pas new
explicitement.