- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
Итератор играет главную роль в определении класса list в библиотеке STL. Итераторы используются для идентификации места вставки или удаления элементов. Кроме того, их используют для “навигации” по списку вместо оператора индексирования. Такое применение итераторов очень похоже на использование указателей при перемещении по массивам и векторам, описанном в разделах 20.1 и 20.3.1. Этот вид итераторов является основным в стандартных алгоритмах (разделы 21.1–21.3).
Почему в классе list не используется индексирование? Мы могли бы проиндексировать узлы, но эта операция удивительно медленная: для того чтобы достичь элемента lst[1000], нам пришлось бы начинать с первого элемента и пройти все элементы по очереди, пока мы не достигли бы элемента с номером 1000. Если вы хотите этого, то можете реализовать эту операцию сами (или применить алгоритм advance(); см. раздел 20.6.2). По этой причине стандартный класс list не содержит операции индексирования.
Мы сделали тип итератора для списка членом класса (вложенным классом), потому что нет никаких причин делать его глобальным. Он используется только в списках. Кроме того, это позволяет нам называть каждый тип в контейнере именем iterator. В стандартной библиотеке есть list<T>::iterator, vector<T>::iterator, map<K,V>::iterator и т.д.
20.4.2. Итерация
Итератор списка должен обеспечивать выполнение операций *, ++, == и !=. Поскольку стандартный список является двухсвязным, в нем также есть операция –– для перемещения назад, к началу списка.
template<class Elem> class list<Elem>::iterator {
Link<Elem>* curr; // текущий узел
public:
iterator(Link* p):curr(p) { }
// вперед
iterator& operator++() {curr = curr–>succ; return *this; }
// назад
iterator& operator––() { curr = curr–>prev; return *this; }
// (разыменовать)
Elem& operator*() { return curr–>val; } // получить значение
bool operator==(const iterator& b) const
{ return curr==b.curr; }
bool operator!= (const iterator& b) const
{ return curr!=b.curr; }
};
Эти функции короткие, простые и эффективные: в них нет циклов, нет сложных выражений и подозрительных вызовов функций. Если эта реализация вам не понятна, то посмотрите на диаграммы, приведенные ранее. Этот итератор списка просто представляет собой указатель на узел с требуемыми операциями. Несмотря на то что реализация (код) для класса list<Elem>::iterator сильно отличается от обычного указателя, который использовался в качестве итератора для векторов и массивов, их семантика одинакова. По существу, итератор списка обеспечивает удобные операции ++, ––, *, ==, and != для указателя на узел.
Посмотрим на функцию high() еще раз.
template<class Iterator >
Iterator high(Iterator first, Iterator last)
// возвращает итератор на максимальный элемент в диапазоне
// [first,last)
{
Iterator high = first;
for (Iterator p = first; p!=last; ++p)
if (*high<*p) high = p;
return high;
}
Мы можем применить ее к объекту класса list.
void f()
{
list<int> lst;
int x;
while (cin >> x) lst.push_front(x);
list<int>::iterator p = high(lst.begin(), lst.end());
cout << "Максимальное значение = " << *p << endl;
}
Здесь значением аргумента класса Iterator argument является класс list<int>::iterator, а реализация операций ++, * и != совершенно отличается от массива, хотя ее смысл остается неизменным. Шаблонная функция high() по-прежнему перемещается по данным (в данном случае по объекту класса list) и находит максимальное значение. Мы можем вставлять элементы в любое место списка, так что мы использовали функцию push_front() для добавления элементов в начало списка просто для иллюстрации. С таким же успехом мы могли бы использовать функцию push_back(), как делали это для объектов класса vector.
ПОПРОБУЙТЕ
В стандартном классе vector нет функции push_front(). Почему? Реализуйте функцию push_front() для класса vector и сравните ее с функцией push_back().
Итак, настало время спросить: “А что, если объект класса list будет пустым?” Иначе говоря, “что если lst.begin()==lst.end()?” В данном случае выполнение инструкции *p будет попыткой разыменования элемента, следующего за последним, т.е. lst.end(). Это катастрофа! Или, что еще хуже, в результате можно получить случайную величину, которая исказит правильный ответ.
Последняя формулировка вопроса содержит явную подсказку: мы можем проверить, пуст ли список, сравнив итераторы begin() и end(), — по существу, мы можем проверить, пуста ли последовательность, сравнивая ее начало и конец.
Существует важная причина, по которой итератор end устанавливается на элемент, следующий за последним, а не на последний элемент: пустая последовательность — не особый случай. Мы не любим особые случаи, потому что — по определению — для каждого из них приходится писать отдельный код.
В нашем примере можно поступить следующим образом:
list<int>::iterator p = high(lst.begin(), lst.end());
if (p==lst.end()) // мы достигли конца?
cout << "Список пустой";
else
cout << "максимальное значение = " << *p << endl;
Работая с алгоритмами из библиотеки STL, мы систематически используем эту проверку. Поскольку в стандартной библиотеке список предусмотрен, не будем углубляться в детали его реализации. Вместо этого кратко укажем, чем эти списки удобны (если вас интересуют детали реализации списков, выполните упр. 12–14).
20.5. Еще одно обобщение класса vector
Из примеров, приведенных в разделах 20.3 и 20.4, следует, что стандартный вектор имеет член класса, являющийся классом iterator, а также функции-члены begin() и end() (как и класс std::list). Однако мы не указали их в нашем классе vector в главе 19. Благодаря чему разные контейнеры могут использоваться более

