2016-05-21 10 views
0

Короче говоря, мне нужно закодировать хэш-таблицу с использованием линейного хэширования на C++ для университета. Хэш-таблица работает, но ресурсы не освобождаются, что является проблемой, особенно, что модульный тест проверяет таблицу со значениями 100 к +, а оставшийся мусор огромен. В принципе, когда я создаю новый Hashtable я делаю следующее:Как удалить динамический массив объектов с указателями на другие объекты (C++)

hashTable = new Bucket[this->tableSize]; 
     for (size_t i = 0; i < tableSize; i++) { 
      hashTable[i] = * new Bucket(); 
     } 

Каждый ковш может содержать указатель на другой перепускной ведро, которое может или не может быть установлен.

class Bucket { 
    private: 
     size_t bucketSize;                 
     size_t elementsInBucket;                
     E v[N]; // int v[N];                
     bool hasOverflow;                  
     Bucket * nextBucket = nullptr; 

Мой вопрос, как я могу удалить всю хеш-таблицу, включая ковши с их потенциальными ведрами перелива в следующем только освобождает половину занимаемой памяти.

delete[] hashTable; 
hashTable = nullptr; 

Спасибо!

+0

«Ведро» по существу является лишь узлом связанного списка. Итак, какой обычный способ удалить связанный список? – rwols

+0

Я не вижу деструктора для 'Bucket'. – Logicrat

+0

'virtual ~ Bucket() { delete nextBucket; } 'Если я кодирую деструктор, программа прерывается, и я получаю EXC_BAD_ACCESS при расширении массива. – cookiemonster

ответ

1

Если я не ошибаюсь, то следующая строка кода является утечка памяти:

hashTable[i] = * new Bucket(); 

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

Вместо этого, вы должны хранить указатели в массиве, как, например:

hashTable = new *Bucket[this->tableSize]; 
for (size_t i = 0; i < tableSize; i++) { 
    hashTable[i] = new Bucket(); 
} 

и удалить его как таковой:

for (size_t i = 0; i < tableSize; i++) { 
    delete hashTable[i]; 
    hashTable[i] = nullptr; 
} 
delete[] hashTable; 
hashTable = nullptr; 

Вы также должны убедиться, что деструктор удаляет указатель элемента, так что когда вы вызываете delete на каждом указателе Bucket, вложенная память освобождается:

~Bucket() { 
    delete nextBucket; 
    nextBucket = nullptr; 
} 

L аст, вам нужно будет изменить любой код, который делает это:

hashTable[i].something 

к этому:

hashTable[i]->something 

Это, мне кажется, что правильный способ обработки динамических массивов.

+0

Спасибо! Я попробую завтра, потому что здесь немного поздно: D – cookiemonster

3

Вы сразу протечки один Bucket на этой линии:

hashTable[i] = * new Bucket(); 

Что это делает:

  1. Выделяют новый Bucket и возвращает указатель на него
  2. разыменования возвращенного указателя и передать ссылку на ваш новый Bucket на Bucket::operator=
  3. Скопируйте пустой Bucket в уже существующий объект hashTable[i]
  4. Выбросьте указатель на ваш вновь распределённая Bucket, таким образом, протекает она

hashTable является указателем на первый элемент массива tableSizeBucket с. Эти объекты уже существуют, поэтому вам не нужно выделять новые в своем цикле.

Кроме того, вы не указали деструктор для Bucket или не показали, как вы выделяете Bucket::nextBucket. Я предполагаю, что каждый Bucket должен владеть ИТС nextBucket, так что вы должны иметь деструктор, который делает что-то вроде

Bucket::~Bucket() 
{ 
    delete nextBucket; 
} 
+0

Деструктор очень похож на тот, который вы написали. В дополнение к этому я также присваиваю nextBucket nullptr. Что касается выделения nextBucket, вызывается метод add (const E & e) для добавления объекта в ведро. Если текущее ведро заполнено, создается новое ведро, и объект добавляется в это ведро. Проблема в том, что при использовании такого деструктора я получаю EXC_BAD + ACCESS – cookiemonster

+0

Что-то, вероятно, неправильно в вашем методе 'add'. Скорее всего, что-то вызывает двойное или бесплатное использование. –

+0

Ошибка появляется при проверке наличия других ковров переполнения. Но спасибо! Я посмотрю его утром. – cookiemonster