<MyRusakov.ru />

WordPress 6 с Нуля до Гуру

WordPress 6 с Нуля до Гуру

Этот курс научит Вас созданию самых разных сайтов на самой популярной в мире CMS - WordPress. Вы увидите установку и настройку локального сервера, разбор каждой настройки, каждой кнопки и каждого пункта меню в панели WordPress.

Также Вы получите и всю практику, поскольку прямо в курсе с нуля создаётся полноценный Интернет-магазин, который затем публикуется в Интернете. И всё это прямо на Ваших глазах.

Помимо уроков к курсу идут упражнения для закрепления материала.

И, наконец, к курсу идёт ценнейший Бонус по тому, как используя ChatGPT и создавая контент для сайта, можно выйти на пассивный доход. Вы наглядно увидите, как зарегистрироваться в ChatGPT (в том числе, и если Вы из России), как правильно выбрать тему для сайта, как правильно генерировать статьи для него(чтобы они индексировались поисковыми системами) и как правильно монетизировать трафик на сайте.

Подробнее
Подписка

Подпишитесь на мой канал на YouTube, где я регулярно публикую новые видео.

YouTube Подписаться

Подписавшись по E-mail, Вы будете получать уведомления о новых статьях.

Подписка Подписаться

Добавляйтесь ко мне в друзья ВКонтакте! Отзывы о сайте и обо мне оставляйте в моей группе.

Мой аккаунт Мой аккаунт Моя группа
Опрос

Какая тема Вас интересует больше?

Итераторы в C++: понятное руководство для начинающих с примерами и ошибками новичков

Итераторы в C++: понятное руководство для начинающих с примерами и ошибками новичков

Поисковый запрос, под который оптимизирована статья: «итераторы в C++» и «итераторы C++ для начинающих».

Что такое итераторы в C++ и зачем они нужны

Итератор — это «указатель-подобный» объект, который позволяет перебирать элементы контейнера и передавать поддиапазоны в алгоритмы стандартной библиотеки. Благодаря итераторам алгоритмы не зависят от конкретного контейнера: один и тот же std::sort сортирует std::vector, а std::find ищет в std::list или std::string — всё через единый интерфейс begin/end.

Базовый синтаксис: begin, end, инкремент и разыменование

#include <vector>
#include <iostream>

int main() {
    std::vector<int> v {1, 2, 3};

    // Итерация с помощью итераторов
    for (auto it = v.begin(); it != v.end(); ++it) {
        std::cout << *it << " "; // *it — доступ к значению
    }
}

Ключевые операции: *it (разыменование), ++it (переход к следующему), сравнение с end() (конец диапазона). Никогда не разыменовывайте итератор, равный end() — это UB (неопределённое поведение).

Константные итераторы: защищаем данные от изменений

Если изменять элементы не нужно, используйте const_iterator или удобные cbegin()/cend().

#include <vector>
#include <iostream>

int main() {
    const std::vector<int> v {10, 20, 30};

    // v.begin() у const-объекта уже const_iterator,
    // но можно явно: v.cbegin(), v.cend()
    for (auto it = v.cbegin(); it != v.cend(); ++it) {
        // *it = 42; // Ошибка компиляции — нельзя менять
        std::cout << *it << " ";
    }
}

Итерация по std::map: пара key/value

#include <map>
#include <string>
#include <iostream>

int main() {
    std::map<std::string, int> scores {{"Ann", 5}, {"Bob", 8}};

    for (auto it = scores.begin(); it != scores.end(); ++it) {
        std::cout << it->first << ": " << it->second << "\n";
    }
}

Элемент map — это std::pair<const Key, T>, поэтому доступ через it->first (ключ) и it->second (значение).

Категории итераторов (коротко и по делу)

  • Input — только чтение по одному проходу (потоки).
  • Forward — многократный проход вперёд (например, forward_list).
  • Bidirectional — как Forward + шаг назад (например, list, map).
  • RandomAccess — произвольный доступ и арифметика (например, vector, deque).
  • Contiguous (C++20) — элементы в непрерывной памяти (например, vector, string).

Чем «сильнее» категория, тем больше операций поддерживается (например, it + n доступно только для RandomAccess).

Алгоритмы STL с итераторами: must‑have примеры

#include <vector>
#include <algorithm>   // find, sort, remove_if
#include <numeric>     // accumulate
#include <iostream>

int main() {
    std::vector<int> v {3, 1, 4, 1, 5, 9};

    // Поиск первого вхождения 4
    auto it = std::find(v.begin(), v.end(), 4);
    if (it != v.end()) std::cout << "Нашли: " << *it << "\n";

    // Сортировка (RandomAccess итераторы)
    std::sort(v.begin(), v.end());

    // Сумма элементов
    int sum = std::accumulate(v.begin(), v.end(), 0);
    std::cout << "Сумма: " << sum << "\n";

    // Удаление нечётных: erase + remove_if (идиома erase-remove)
    v.erase(std::remove_if(v.begin(), v.end(), [](int x){ return x % 2 != 0; }), v.end());
}

Идиома erase-remove — базовый приём: remove_if сдвигает «ненужные» в конец и возвращает новый логический конец, а erase физически удаляет хвостовой диапазон.

Инвалидация итераторов: где тонко — там рвётся

  • vector: вставки/удаления в середине и рост емкости могут инвалидировать все итераторы, ссылки и указатели на элементы. Безопаснее заново получать итераторы после модификаций.
  • list, forward_list: итераторы сохраняются при вставках/удалениях других элементов, инвалидируется только удалённый элемент.
  • map, set: вставки сохраняют валидность других итераторов; удаление инвалидирует итераторы на удалённые элементы.
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v {1,2,3,4,5};
    auto it = v.begin(); // Указывает на 1

    // Вставка может перераспределить память и сделать it невалидным
    v.insert(v.begin() + 2, 42);

    // Нельзя больше использовать старый it — возьмите заново:
    it = v.begin();
    std::cout << *it; // ОК
}

Диапазоны C++20 (ranges): чище, короче, безопаснее

Модерновый подход — не таскать пары begin(), end(), а работать с «диапазонами» и конвейерами представлений (views).

#include <vector>
#include <ranges>
#include <iostream>

int main() {
    std::vector<int> v {3,1,4,1,5,9,2,6};

    // Отфильтровать чётные и умножить на 10, затем вывести
    auto pipe = v | std::views::filter([](int x){ return x % 2 == 0; })
                  | std::views::transform([](int x){ return x * 10; });

    for (int x : pipe) std::cout << x << " ";
}

Компиляция с поддержкой C++20: для g++ -std=c++20, для MSVC выберите стандарт в настройках проекта. Диапазоны уменьшают ошибки с границами и улучшают читаемость.

Частые ошибки новичков

  • Разыменование end() или итератора на удалённый элемент.
  • Хранение итераторов через долгие промежутки и повторное использование после модификаций контейнера.
  • Неправильная работа с erase в цикле: пропуск элементов. Решение — использовать возвращаемое значение erase как новый итератор.
  • Излишнее копирование: там, где достаточно const_iterator или диапазонов, используют мутабельные итераторы.
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v {1,2,3,4,5};
    for (auto it = v.begin(); it != v.end(); ) {
        if (*it % 2 == 0) {
            it = v.erase(it); // Возвращает итератор на следующий элемент
        } else {
            ++it;
        }
    }

    for (int x : v) std::cout << x << " "; // 1 3 5
}

Мини‑практика: удалить дубликаты из vector

Классический приём: сортировка + unique + erase.

#include <vector>
#include <algorithm>
#include <iostream>

int main() {
    std::vector<int> v {5,1,2,1,3,2,4,3};

    std::sort(v.begin(), v.end());
    auto last = std::unique(v.begin(), v.end());
    v.erase(last, v.end());

    for (int x : v) std::cout << x << " "; // 1 2 3 4 5
}

Здесь unique возвращает итератор на первый «повтор», а erase удаляет хвост диапазона дубликатов.

Лучшие практики

  • Предпочитайте range-based for и C++20 ranges там, где это уместно — меньше кода и ошибок.
  • Используйте const_iterator или cbegin/cend, если не изменяете элементы — так вы документируете намерение и избегаете случайных модификаций.
  • После операций, которые могут инвалидировать итераторы (вставки, удаление, изменение ёмкости), получайте их заново.
  • Для удаления по условию применяйте идиому erase-remove или цикл с использованием возвращаемого erase.

Заключение

Итераторы — фундаментальный инструмент C++: с ними вы эффективно используете контейнеры и алгоритмы STL, пишете менее связанный и более безопасный код. Освойте базовые паттерны (erase-remove, const_iterator), не забывайте о правилах инвалидации и постепенно переходите к C++20 ranges — это сделает ваш код короче и понятнее.

Хотите системно прокачать язык и научиться писать производительный и современный C++‑код? Рекомендую пройти практический курс: Прокачать C++ с нуля до уровня уверенного разработчика — перейти к курсу.

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (https://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: https://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: https://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как создать свой сайт

  2. Текстовая ссылка:

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (0):

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.