2013-08-31 2 views
-1

J'ai affaire à un map, dont le deuxième élément est également un map, dont le deuxième élément est un vector. Et pendant le processus de construction de la carte, il semble que je doive allouer dynamiquement la mémoire, mais je n'arrive pas à libérer la mémoire correctement. Mon problème peut être réduit au code source ci-dessous.Où est-ce que je me trompe dans le destructeur pour ce conteneur C++?

Je n'arrive pas à comprendre pourquoi le desconducteur est incorrect.

De plus, existe-t-il un meilleur moyen d'éviter les fuites de mémoire dans ce cas?

#include <vector> 
#include <map> 
#include <iostream> 

using namespace std; 

typedef vector<int> IntVect; 
typedef map<int, IntVect> NumEle; 
typedef map<int, NumEle> Nums; 

class NumLess { 
public: 
    Nums numSet; 
    ~NumLess() { 
    for (Nums::iterator I = numSet.begin(), E = numSet.end(); I != E; ++I) { 
     NumEle &numEle = I->second; 
     for (NumEle::iterator II = numEle.begin(), EE = numEle.end(); II != EE; ++II) { 
     IntVect &intVect = II->second; 
     intVect.clear(); 
     delete &intVect; 
     } 
     delete &numEle; 
    } 
    } 
    friend ostream &operator<<(ostream &os, const NumLess &numLess) { 
    for (Nums::const_iterator I = numLess.numSet.begin(), 
           E = numLess.numSet.end(); 
     I != E; ++I) { 
     const NumEle &numEle = I->second; 
     os << "NumEle:" << I->first << endl; 
     for (NumEle::const_iterator II = numEle.begin(), EE = numEle.end(); 
      II != EE; ++II) { 
     os << "IntVect " << II->first << " | "; 
     const IntVect &intVect = II->second; 
     for (auto i : intVect) { 
      os << i << " "; 
     } 
     os << endl; 
     } 
    } 
    return os; 
    } 
}; 

int main(void) { 
    NumLess numLess; 
    for (unsigned h = 4; h > 0; --h) { 
    NumEle *numEle = new NumEle(); 
    for (unsigned i = h; i > 0; --i) { 
     IntVect *intVect = new IntVect(); 
     for (unsigned j = 0; j < i; ++j) { 
     intVect->push_back(j); 
     } 
     numEle->insert(pair<int, IntVect>(i, *intVect)); 
    } 
    numLess.numSet.insert(pair<int, NumEle>(h, *numEle)); 
    } 
    cout << numLess; 
    cout << "finished" << endl; 
    return 0; 
} 
+1

[ne pas utiliser 'new'] (http://klmr.me/slides/modern-cpp/#1) et vous avez déjà considérablement réduit vos chances d'une fuite de mémoire. – chris

+0

@chris Mais je ne connais pas la bonne structure de données pour éviter l'utilisation de 'new'. –

Répondre

1

Pour faire une histoire très courte: vous supprimez l'objet que vous ne l'avez pas allouez. Pour le réparer, vous devez supprimer les suppressions de votre destructeur.

Vous avez également une fuite dans votre main. Vous créez des objets sur le tas et ne le libérez jamais. Les objets créés sont copiés dans les conteneurs. Pour corriger cette fuite, supprimez les nouveaux et ajoutez simplement des objets dans des conteneurs.


Si vous préférez travailler avec des pointeurs (mauvais à mon avis), vous devez changer vos typedefs:

typedef map<int, IntVect*> NumEle; 
typedef map<int, NumEle*> Nums; 

est ici 'main()' sans 'nouvelle' et fuite de mémoire:

int main(void) { 
    NumLess numLess; 
    for (unsigned h = 4; h > 0; --h) { 
    NumEle numEle; 
    for (unsigned i = h; i > 0; --i) { 
     IntVect intVect; 
     for (unsigned j = 0; j < i; ++j) { 
     intVect.push_back(j); 
     } 
     numEle.insert(pair<int, IntVect>(i, intVect)); 
    } 
    numLess.numSet.insert(pair<int, NumEle>(h, numEle)); 
    } 
    cout << numLess; 
    cout << "finished" << endl; 
    return 0; 
} 
+0

Mais je pense que j'utilise le destructeur pour libérer la mémoire indirectement. –

+0

@HongxuChen Supprimez simplement les lignes avec 'new' et 'delete' dans votre code, et voyez comment cela corrige votre programme. Votre destructeur n'a rien à faire. Le destructeur du contreur fera ce qui doit être fait. –

+0

Je trouve juste qu'il est difficile pour moi de rendre le code exécutable sans 'new'. Par exemple, 'numEle' sera détruit une fois la boucle terminée (' Ai-je raison? '), Et dans le code réel, je dois utiliser 'numLess.numSet' pour une utilisation future. –

Questions connexes