Итераторы
Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy — урок 72 из 104.
Итераторы — это объекты, которые выступают в роли моста между контейнерами и алгоритмами. Они обеспечивают единообразный способ доступа к элементам в любом контейнере, независимо от того, как этот контейнер хранит свои данные внутри. Представьте итератор как обобщенный указатель, который знает, как перемещаться по контейнеру.
Каждый контейнер STL предоставляет методы begin() и end(). Итератор begin() указывает на первый элемент, в то время как end() указывает на элемент, следующий за последним — сторожевое значение (sentinel), которое отмечает место остановки:
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums = {10, 20, 30};
for (std::vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) {
std::cout << *it << " "; // Разыменование для получения значения
}
// Вывод: 10 20 30
}Ключевое слово auto значительно упрощает объявление итераторов:
for (auto it = nums.begin(); it != nums.end(); ++it) {
*it *= 2; // Изменяем элементы через итератор
}
// nums теперь {20, 40, 60}Итераторы делятся на различные категории в зависимости от их возможностей. Итераторы произвольного доступа (например, итераторы vector) поддерживают арифметические операции, такие как it + 3 или it1 - it2.
Двунаправленные итераторы (из list, map) могут перемещаться вперед и назад с помощью ++ и --. Однонаправленные итераторы могут перемещаться только в одном направлении.
Для обратного обхода используйте rbegin() и rend():
for (auto rit = nums.rbegin(); rit != nums.rend(); ++rit) {
std::cout << *rit << " "; // Выводит в обратном порядке
}Задание
ЛегкоДавайте создадим систему отслеживания инвентаря, которая использует итераторы для обхода и управления коллекциями предметов. Вы попрактикуетесь в использовании различных типов итераторов для навигации по данным разными способами.
Вы организуете свой код в двух файлах:
Inventory.h: Определите классInventory, который управляет коллекцией количеств предметов, хранящихся вstd::vector<int>.Ваш класс должен предоставлять следующие методы:
addItem(int quantity)— добавляет количество предметов в инвентарьprintForward()— использует итераторы сbegin()иend()для вывода всех количеств, разделенных пробелами, за которыми следует символ новой строкиprintReverse()— использует обратные итераторы сrbegin()иrend()для вывода всех количеств в обратном порядке, разделенных пробелами, за которыми следует символ новой строкиdoubleAll()— использует итераторы для обхода вектора и удвоения каждого количества на местеgetTotal()— использует итераторы для вычисления и возврата суммы всех количеств
Используйте ключевое слово
autoдля объявлений итераторов, чтобы код оставался чистым.main.cpp: Считайте четыре целых числа (каждое на отдельной строке), представляющих количество предметов.Создайте объект
Inventoryи добавьте все четыре количества. Затем продемонстрируйте использование итераторов:- Выведя
"Forward: ", а затем вызвавprintForward() - Выведя
"Reverse: ", а затем вызвавprintReverse() - Выведя
"Total: ", за которым следует результатgetTotal() - Вызвав
doubleAll()для изменения количеств - Выведя
"After doubling: ", а затем вызвавprintForward() - Выведя
"New total: ", за которым следует результатgetTotal()
- Выведя
Например, при входных данных 10, 25, 15 и 30:
Forward: 10 25 15 30
Reverse: 30 15 25 10
Total: 80
After doubling: 20 50 30 60
New total: 160Эта задача позволит вам попрактиковаться как в чтении элементов через итераторы (для вывода и суммирования), так и в изменении элементов через итераторы (для удвоения). Вы также увидите, как обратные итераторы делают обход в обратном направлении простым без каких-либо манипуляций с индексами.
Шпаргалка
Итераторы — это объекты, которые предоставляют единообразный способ доступа к элементам в контейнерах. Они действуют как обобщенные указатели, которые знают, как перемещаться по контейнеру.
Каждый контейнер STL предоставляет методы begin() и end(). Итератор begin() указывает на первый элемент, в то время как end() указывает на элемент, следующий за последним:
std::vector<int> nums = {10, 20, 30};
for (std::vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) {
std::cout << *it << " "; // Разыменование для получения значения
}Используйте ключевое слово auto, чтобы упростить объявление итераторов:
for (auto it = nums.begin(); it != nums.end(); ++it) {
*it *= 2; // Изменение элементов через итератор
}Категории итераторов в зависимости от их возможностей:
- Итераторы произвольного доступа (например,
vector) поддерживают арифметические операции, такие какit + 3илиit1 - it2 - Двунаправленные итераторы (например,
list,map) могут перемещаться вперед и назад с помощью++и-- - Однонаправленные итераторы могут перемещаться только в одном направлении
Для обратного обхода используйте rbegin() и rend():
for (auto rit = nums.rbegin(); rit != nums.rend(); ++rit) {
std::cout << *rit << " "; // Выводит в обратном порядке
}Попробуйте сами
#include <iostream>
#include "Inventory.h"
using namespace std;
int main() {
// Считать четыре целых числа
int q1, q2, q3, q4;
cin >> q1;
cin >> q2;
cin >> q3;
cin >> q4;
// TODO: Создать объект Inventory
// TODO: Добавить все четыре количества в инвентарь
// TODO: Вывести "Forward: ", затем вызвать printForward()
// TODO: Вывести "Reverse: ", затем вызвать printReverse()
// TODO: Вывести "Total: ", а затем результат getTotal()
// TODO: Вызвать doubleAll() для изменения количеств
// TODO: Вывести "After doubling: ", затем вызвать printForward()
// TODO: Вывести "New total: ", а затем результат getTotal()
return 0;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыСборка и компиляция C++Заголовочные файлы и файлы исходного кодаПространства имен и область видимостиВведение в ООП на C++Классы и объектыУказатель 'this'Методы (функции-члены)Атрибуты (члены данных)Основы конструкторов и деструкторовИтоги — Простой калькулятор4Свойства классов
Члены экземпляра против статическихГеттеры и сеттерыКонстантные функции-членыКлючевое слово mutableСтатические методы и переменныеДружественные функции и классыИтоги — Менеджер банковских счетов7Наследование
Основы наследованияУровни доступа при наследованииПорядок вызова конструкторов и деструкторовПереопределение методовВиртуальные функции и VTableМножественное наследованиеВиртуальное наследованиеИтоги — Иерархия сотрудников10Обзор STL
Обзор и философия STLКонтейнеры STLИтераторыАлгоритмы STLФункторы и лямбда-выраженияИтоги: частота слов13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonFactory и Abstract FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy2Управление памятью
Стек и кучаУказатели и ссылкиДинамическая память (new/delete)Умные указатели в C++RAII в C++Итоги — Менеджер динамического массива5Инкапсуляция
Спецификаторы доступа в C++Спецификаторы доступа: подробный разборСокрытие данныхStruct против ClassВложенные и внутренние классыИтоги — Система учета студентов8Полиморфизм
Полиморфизм компиляции и времени выполненияПерегрузка функцийВиртуальные функции: повторениеЧистые виртуальные функцииАбстрактные классыПроектирование интерфейсов на C++Dynamic Casting и RTTIИтоги: Калькулятор фигур11Продвинутые концепции ООП
Композиция против наследованияМиксины через CRTPИдиома PimplСтирание типовEnum Classes и строгая типизацияОбработка исключений в ООППользовательские иерархии исключений14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикRAII как паттерн3Конструкторы и деструкторы
Конструктор по умолчаниюПараметризованный конструкторКонструктор копированияКонструктор перемещенияСписки инициализации конструктораДелегирующие конструкторыГлубокое погружение в деструкторыПравило трех / пяти / нуляПовторение — класс String6Перегрузка операторов
Введение в перегрузку операторовПерегрузка арифметических операторовПерегрузка операторов сравненияОператоры потоковПерегрузка оператора присваиванияПерегрузка операторов [] и ()Операторы преобразования типовИтоги — класс Matrix9Шаблоны
Шаблоны функцийШаблоны классовСпециализация шаблоновВариативные шаблоныОсновы SFINAE и Type TraitsИтоги — Обобщенный контейнер