2013-08-31 1 views
-1

Я имею дело с map, вторым элементом которого также является map, вторым элементом которого является vector. И во время процесса построения карты мне кажется, что я должен распределять память динамически, но тогда я не могу правильно освободить память. Моя проблема может быть сведена к исходному коду ниже.Где я ошибаюсь в деструкторе для этого контейнера C++?

Я просто не могу понять, почему desctructor неверен.

Кроме того, есть ли лучший способ избежать утечки памяти в этом случае?

#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

[не используйте 'new'] (http://klmr.me/slides/modern-cpp/#1) и вы уже значительно снизила свои шансы на утечку памяти. – chris

+0

@chris Но я просто не знаю правильной структуры данных, чтобы избежать использования 'new'. –

ответ

1

Чтобы сделать длинную историю очень коротким: вы удаляете объект, который вы не выделили. Чтобы исправить это, вам нужно удалить удаленные данные из деструктора.

У вас также есть утечка в вашем главном. Вы создаете объекты в куче и никогда не выпускаете. Созданные объекты копируются в контейнеры. Чтобы устранить эту утечку, удалите новые и просто добавьте объекты в контейнеры.


Если вы предпочитаете работать с указателями (плохой на мой взгляд), вам необходимо изменить определений типов:

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

Вот «главный()» без «новый» и утечка памяти:

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

Но я думаю, что я использую деструктор, чтобы освободить память косвенно. –

+0

@HongxuChen Просто удалите строки с «новым» и «удалите» в своем коде и посмотрите, как это исправляет вашу программу. Ваш деструктор не должен ничего делать. Деструктор десанта сделает то, что нужно сделать. –

+0

Я просто нахожу, что мне сложно сделать код runnable без 'new'. Например, 'numEle' будет уничтожен после завершения цикла (' Am I right? '), А в реальном коде я должен использовать' numLess.numSet' для будущего использования. –

Смежные вопросы