Здесь важно запомнить, что vector хранит delete. Если выделить память, затем поместить указатели в память vector, то по окончании работы следует самостоятельно удалить память. Не дайте ввести себя в заблуждение термину «контейнер», думая, что если в vector сохранить указатель, то это подразумевает владение им.
После удаления указателей следует явно очистить vector — по той же причине, по которой следует присваивать переменным-указателям по окончании работы с ними значение NULL. Это предотвратит ошибочное повторное удаление.
6.5. Хранение объектов в списке
Требуется хранить элементы в виде последовательности, но vector не соответствует всем требованиям. В частности, требуется иметь возможность эффективно добавлять и удалять элементы в середине последовательности, а не только в ее конце.
Для хранения данных используйте list, объявленный в . list предлагает более высокую производительность и большую гибкость при изменении последовательности в произвольных местах. Пример 6.5 показывает, как использовать list, а также демонстрирует некоторые из его уникальных операций.
#include
#include
#include
#include
using namespace std;
// Простая функция для печати
template
struct printer {
void operator()(const T& s) {
cout << s << '\n';
}
};
bool inline even(int n) {
return(n % 2 == 0);
}
printer
printer
int main() {
list
list
lstOne.push_back("Red");
lstOne.push_back("Green");
lstOne.push_back("Blue");
lstTwo.push_front("Orange");
lstTwo.push_front("Yellow");
lstTwo.push_front("Fuschia");
for_each(lstOne.begin(), // Напечатать каждый элемент списка,
lstOne.end(), // используя пользовательскую функцию печати
strPrinter);
lstOne.sort(); // list содержит методы для сортировки
lstTwo.sort();
lstOne.merge(lstTwo); // Объединить два списка и напечатать
for_each(lstOne.begin(), // результаты (перед объединением списки должны
lstOne.end(), // быть отсортированы)
strPrinter);
list
intLst.push_back(0);
intLst.push_back(1);
intLst.push_back(2);
intLst.push_back(3);
intLst.push_back(4);
// Удалить все значения больше 2
intLst.remove_if(bind2nd(greater
for_each(intLst.begin(), intLst.end(), intPrinter);
// Или удалить все четные значения
intLst.remove_if(even);
}
list — это последовательность, обеспечивающая постоянную сложность операций вставки и удаления элементов в произвольную позицию, но обладающая линейной сложностью их поиска. Обычно list реализуется как двухсвязный список, что означает, что каждый элемент хранится в узле, содержащем указатели на предыдущий и следующий элементы последовательности. Он обеспечивает все требования к контейнеру стандартной последовательности, полюс предоставляет несколько уникальных методов.
Объявление list не вызывает сложностей — просто укажите тип элементов, которые в нем будут храниться, и, опционально, класс распределителя памяти.
list
typename Allocator = allocator
// памяти
Параметр шаблона Value — это тип элементов, которые будут храниться в list. Это должен быть тип, который поддерживает конструктор копирования и присвоение. Allocator — это используемый класс распределителя памяти. По умолчанию используется стандартный распределитель (и в большинстве случаев его вполне достаточно).
Далее приведено типичное объявление list (см. пример 6.5).
list
После объявления списка поместите в него что-нибудь с помощью push_front или push_back, как здесь.