2010-09-09 5 views
3

i ont la structure suivante:la suppression d'un tableau de pointeur sur struct

struct Message { 
    Agent *_agent; 
    double _val; 
}; 

et le réseau REE suivant:

typedef Message* MessageP; 
MessageP *_msgArr; 
_msgArr = new MessageP[MAX_MESSAGES]; 

ceci est la méthode qui insère un message à la matrice:

void Timing::AddMessage(Agent * const agentPtr, double val) { 

    MessageP msgPtr = new Message; 
    assert(msgPtr != 0); 

    //assign values: 
    (*msgPtr)._agent = agentPtr; 
    (*msgPtr)._val = val; 

    //add to messages array: 
    assert(_msgArr != 0 && _waitingMsgs<MAX_MESSAGES); 
    _msgArr[_waitingMsgs] = msgPtr; 
    _waitingMsgs++; 

} 

Ma question concerne la suppression de ce tableau. Je voudrais supprimer le tableau et toutes les structures allouées. si j'écris:

delete [] _msgArr 

ce sera également supprimer chaque struct alloué ou libérera que la mémoire allouée pour le tableau?

est la bonne façon est d'aller sur l'ensemble du réseau avec une boucle et écrire

delete _msgArr[i] 

et enfin Wite supprimer [] _msgArr pour supprimer le tableau alloué ?

merci!

+4

Avez-vous envisagé d'utiliser l'un des conteneurs de bibliothèque standard comme 'std :: vector' ou' std :: deque'? –

+0

Je suis en train de suivre un cours en C++, nous n'avons pas encore atteint ce matériel donc il n'est pas permis d'utiliser le vecteur .. –

+1

James a un point - les tableaux standard sont très utiles (et souvent plus efficace en ressources, si un peu plus lent parfois) - mais selon la réponse ci-dessous, vous devez toujours supprimer les objets pointés dans les conteneurs std. – Ragster

Répondre

2

Le delete [] appellera les destructeurs sur les pointeurs de structure, qui ne disposent pas des structures ou des membres _agent, qui lui-même pointe vers la mémoire. Vous pouvez appeler delete _msgArr[i]._agent puis delete _msgArr[i] dans une boucle, ce qui permettra de disposer du Agent puis du Message. Tout d'abord, cependant, vous devez savoir qui devrait se débarrasser de la Agent s, et quand. Si ceux-ci appartiennent à une autre structure de données, vous ne devriez pas vous en débarrasser en vous débarrassant de _msgArr, et en bouclant sur _delete _msgArr[i] suivi de delete [] _msgarr; est tout ce dont vous avez besoin.

Si vous devez également supprimer les Agent s, vous avez trois choix raisonnables.D'abord, vous pouvez donner Message un destructeur qui supprimera _agent de . Il devrait également avoir un constructeur de copie et un opérateur d'assignation définis, soit pour transmettre la propriété, soit pour copier, ou bien les définir comme private donc toute tentative pour les utiliser sera une erreur de compilation. Deuxièmement, vous pouvez remplacer le Agent * par un pointeur intelligent, de sorte que la mémoire supplémentaire sera supprimée lorsque le Message disparaîtra. Troisièmement, vous pouvez passer par la boucle que j'ai suggérée ci-dessus lorsque vous vous débarrassez de la matrice.

Sauf si vous avez de bonnes raisons de garder le code C compatible, je vous suggère que vous utilisez un std::vector<boost::shared_ptr<Message> >, et ont Message contenir un boost::shared_ptr<Agent> plutôt que d'un Agent * (si vous ne disposez pas de disposer des Agent s , Agent * va bien). À ce stade, vous n'avez pas à vous inquiéter: lorsque _msgArr est hors de portée, toute la mémoire est nettoyée correctement.

+0

Pouvez-vous expliquer votre deuxième option - l'utilisation d'un pointeur intelligent qui supprimera toute la mémoire lorsque le message est supprimé? –

4

Oui, vous devez boucler tous les éléments et delete manuellement avant d'appeler delete[] sur la baie.

+0

Donc, d'après ce que je comprends, delete [] _msgArr n'appelle pas delete sur chaque cellule. quelle est la signification de supprimer _msgArr sans le []? –

+0

Je veux dire, supprime-t-il aussi le tableau alloué? –

+2

@rob: Si '_msgArr' pointe vers un tableau créé par' new T [N] '(la forme de tableau de' new'), alors 'delete _msgArr' génère un comportement indéfini. Vous devez le supprimer en utilisant la forme array de 'delete'. –

0

malheureusement oui. Mais vous pouvez simplifier la chose avec quelques lignes si vous allez le faire beaucoup.

#include <algorithm> 
// might already exists in a boost header (i don't remember) 
template <T> 
void delete_func(T* e) { 
    delete e; 
} 

// then, to delete your array : 
std::for_each(_msgArr,_msgArr+MAX_MESSAGES, delete_func); 
delete[] _msgArr; 

mais je suggère de ne pas le faire. Vous pouvez utiliser un vecteur std :: avec auto_ptr ou shared_ptr (selon votre cas d'utilisation). Vous n'aurez donc pas à supprimer chaque élément vous-même, car auto_ptr le fera. Il vous suffira de supprimer le fichier std :: vector

0

À l'exception du fait qu'il fait partie d'une classe membre et qu'il utilise new et delete, il s'agit du code C. Vous n'avez pas besoin de vérifier le résultat de new (erreurs d'allocation seront lancées), vous ne devriez pas faire vos propres tableaux dynamiques (c'est ce que std::vector est pour), et vous ne devriez pas gérer dynamiquement alloué en utilisant des pointeurs muets.

Ce que vous voulez est std::vector< std::shared_ptr<Message> > ou l'un des conteneurs de pointeur de boost.