Память утечка, потому что нет деструктора, чтобы освободить выделенные Node
с. Аскер отмечает, что они удалили деструктор, потому что программа потерпела крах, когда у них был тот. Это ошибка, которую нужно было устранить, потому что правильно использовать деструктор.
Решение
Отложите деструктор обратно и решите, почему деструктор вызвал программу к sh .
Решение для Решения
List
нарушает Правило Трех . Это означает, что когда List
копируется, и у вас есть два объекта, каждый из которых указывает на одну и ту же головку Node
. Этот Node
может быть delete
d только один раз, и оба объекта будут пытаться delete
его в деструкторе List
. Рано или поздно программа умирает мучительной смертью.
Обычно вы можете заменить проходы по значению проходами по ссылке, а затем запретить копирование с помощью delete
специальных функций-членов. Например. добавьте
List(const List & src) = delete;
List& operator=(List src) = delete;
к List
и дождитесь, когда компилятор начнет кричать о копировании List
при удалении специальных функций копирования. Замените все проходы по значению проходами по ссылке.
К сожалению
List<bibliography> readBibliographyFile(char * filename)
возвращает по значению. Возврат по локальной ссылке обречен . Локальная переменная выходит из области видимости и уничтожается, оставляя вам ссылку на недопустимый объект. Это означает, что вы должны сделать это трудным путем:
Реализация всех трех специальных функций-членов:
// destructor
~List()
{
while (head)
{
Node<T> * temp = head->next;
delete head;
head = temp;
}
}
// copy constructor
List(const List & src): head(NULL), length(src.length)
{
Node<T> ** destpp = &head; // point at the head.
// using a pointer to a pointer because it hides
// the single difference between head and a Node's
// next member: their name. This means we don't need
// any special cases for handling the head. It's just
// another pointer to a Node.
Node<T> * srcnodep = src.head;
while (srcnodep) // while there is a next node in the source list
{
*destpp = new Node<T>{srcnodep->data, NULL}; // copy the node and store it at
// destination
destpp = &((*destpp)->next); // advance destination to new node
srcnodep = srcnodep->next; // advance to next node in source list
}
}
List& operator=(List src) // pass list by value. It will be copied
{
length = src.length; // Technically we should swap this, but the copy
// is gonna DIE real soon.
// swap the node lists. use std::swap if you can.
Node<T> * temp = head;
head = src.head;
src.head = temp;
// now this list has the copy's Node list and the copy can go out of scope
// and destroy the list that was in this List.
return *this;
}
Примечания
operator=
использует преимущества Копирование и замена идиомы . Часто это не самое быстрое решение, но его легко написать и почти невозможно ошибиться. Я начинаю с Copy и Swap и выполняю миграцию на что-то более быстрое только тогда, когда профилирование производительности кода показывает, что я должен, и это почти никогда не происходит.
Приходит также и трюк с указателем на указатель, используемый в конструкторе копирования. очень удобно, когда вставляет и удаляет элементы списка.
Знает и понимает Правило Трех и его друзей . Вы не можете писать сложные и эффективные программы на C ++ без него. Вполне возможно, что это задание было дано, по крайней мере, частично, чтобы заставить вас выучить его.