Есть класс Cinema
, а так же производные от него. В консольном приложении я создаю список этих классов.
auto cinemas = new std::list<Cinema*>();
cinemas->push_back(new ImaxCinema("Victory square 15/6", "Imax 1", 150, 150));
cinemas->push_back(new Cinema3D("Victory square 16/1", "3D-Cinema", "Spectrum", 14));
cinemas->push_back(new DriveInCinema("Victory square 17/89", "Drive-In", 15, 102.3));
Позже, с помощью цикла, я вывожу содержимое.
for (auto iterator = cinemas->begin(); iterator != cinemas->end(); iterator++)
{
(*iterator)->write();
}
Затем очищаю список и освобождаю память выделенную под список.
cinemas->clear();
delete cinemas;
Вопрос: вызывается ли delete для каждого элемента в списке? Как это можно проверить?
Нет, память неявно не освобождается. Мало того, после вызова clear()
Вы потеряли все имеющиеся указатели и, если они нигде более не сохранены, то Вы уже не сможете освободить память.
Вы можете освободить память в цикле, перед вызовом clear()
:
for (auto p: *cinemas) {
delete p;
}
cinemas->clear();
delete cinemas;
Также Вы можете использовать умные указатели:
auto cinemas = std::make_unique<std::list<std::unique_ptr<Cinema>>>();
cinemas->push_back(std::make_unique<ImaxCinema>("Victory square 15/6", "Imax 1", 150, 150));
cinemas->push_back(std::make_unique<Cinema3D>("Victory square 16/1", "3D-Cinema", "Spectrum", 14));
cinemas->push_back(std::make_unique<DriveInCinema>("Victory square 17/89", "Drive-In", 15, 102.3));
cinemas->clear();//"Умные" указатели уничтожат объекты, которыми владеют
cinemas.reset();//Удаление объекта, которым владеет cinemas
//Или совсем ничего не нужно вызывать, объект будет уничтожен при выходе из области видимости
Формально педантично-правильный способ удаления элементов из контейнера "голых" указателей должен выглядеть примерно так
while (!cinemas->empty())
{
Cinema *cinema = сinemas->back();
cinemas->pop_back();
delete cinema;
}
delete cinemas;
Идея заключается в том, чтобы ни в какой момент времени в контейнере не хранились невалидные указатели. Т.е. в первую очередь удаляется элемент из контейнера, и только затем уничтожается объект, на который этот элемент указывал.
Вариант, который начинает с удаления всех указуемых объектов и только потом удаляет элементы списка, является практически приемлемым для std::list<>
, но запросто может привести к проблемам с другими типами контейнеров (в частности, с ассоциативными контейнерами).
Удалять вручную.
for(auto cinema: *cinemas) delete cinema;
cinemas->clear();
Заставить компилятор сделать это за вас:
auto cinemas = new std::list<std::unique_ptr<Cinema>>();
cinemas->push_back(std::make_unique<ImaxCinema>("Victory square 15/6", "Imax 1", 150, 150));
cinemas->push_back(std::make_unique<Cinema3D>("Victory square 16/1", "3D-Cinema", "Spectrum", 14));
cinemas->push_back(std::make_unique<DriveInCinema>("Victory square 17/89", "Drive-In", 15, 102.3));
cinemas->clear();
PS. А cinemas
должен быть указателем?
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
И почему нельзя использовать объявление using при виртуальном наследовании?
Почему при выполнении кода оба массива постоянно инициализируются (или, по крайней мере, выводятся на экран) одинаковыми числами? https://wwwonlinegdb
Дана задача, в которой надо ввести числа в массив, при этом, вводить их надо через пробел