Реализация простого генератора
Создайте сопрограмму-генератор, которая лениво выдаёт значения.
«Реализация простого генератора» — бесплатный урок C++ Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.
Генераторы как корутины
Генератор — это корутина, которая выдаёт значения по одному. Каждый вызов генератора возвращает следующее значение и приостанавливает выполнение.
Тип Generator
Определите класс с вложенным типом promise_type. Компилятор использует его для управления состоянием корутины.
template <typename T>
struct Generator {
struct promise_type {
T current_value;
Generator get_return_object() {
return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() {}
std::suspend_always yield_value(T value) {
current_value = value;
return {};
}
void unhandled_exception() { std::terminate(); }
};
std::coroutine_handle<promise_type> h;
// ... constructors, destructor, next() ...
};Использование генератора
После определения генераторы воспринимаются почти как конструкция yield в Python.
Generator<int> counting() {
int n = 0;
while (true) co_yield n++;
}
auto g = counting();
for (int i = 0; i < 5; ++i) {
std::cout << g.next() << " ";
}
// 0 1 2 3 4coroutine_handle
Компилятор возвращает объект std::coroutine_handle. Он представляет приостановленную корутину: её можно возобновить с помощью resume(), уничтожить с помощью destroy() или проверить с помощью done().
Точки приостановки
Каждый вызов co_yield приостанавливает выполнение. Когда вызывающий код вызывает resume(), выполнение продолжается до следующей точки приостановки или до конца корутины.
initial_suspend и final_suspend
Две точки настройки:
initial_suspend— возвращайтеsuspend_alwaysдля ленивого запуска иsuspend_neverдля немедленного запускаfinal_suspend— управляет очисткой. Обычно используетсяsuspend_always, чтобы обеспечить корректное уничтожение
C++23 std::generator
В C++23 в <generator> добавлен тип std::generator. Для стандартного случая больше не нужно создавать этот тип вручную.
#include <generator>
std::generator<int> counting() {
int n = 0;
while (true) co_yield n++;
}Цикл по диапазону
Если тип генератора поддерживает begin/end, цикл по диапазону работает без дополнительных действий.
for (int x : counting()) {
if (x >= 10) break;
std::cout << x;
}Семантика извлечения и отправки
Генераторы используют извлечение по запросу — вызывающий код управляет перебором. Корутины, работающие по принципу отправки, представляют собой асинхронные задачи.
Варианты применения
Генераторы отлично подходят для:
- Ленивых последовательностей: чисел Фибоначчи, простых чисел и чтения файлов построчно
- Потоковой обработки данных без их предварительного размещения в памяти
- Обхода древовидных структур
Особенности использования памяти
По умолчанию кадр корутины выделяется в куче. Компилятор может устранить это выделение, если это позволяет встраивание, — измеряйте производительность, когда она важна.
Библиотеки для изучения
Для обучения библиотека cppcoro Льюиса Бейкера предлагает хорошо документированные типы генераторов и задач. Boost.Asio предоставляет ввод-вывод, удобный для корутин. Начиная с C++23 стандартная библиотека также поддерживает корутины.
Быстрая проверка
Какой тип стандартной библиотеки C++23 предназначен для корутин-генераторов?
Итоги
Корутина-генератор лениво выдаёт значения с помощью co_yield. Реализуйте её как класс, содержащий promise_type. В C++23 стандартизирован тип std::generator. Генераторы особенно эффективны для ленивых последовательностей и потоковой обработки.
Часто задаваемые вопросы
Урок «Реализация простого генератора» бесплатный?
Да — полный текст урока «Реализация простого генератора» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.
Чему я научусь в уроке «Реализация простого генератора»?
Создайте сопрограмму-генератор, которая лениво выдаёт значения. Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C++ Academy?
Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Реализация простого генератора»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C++ Academy?
Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Концепции сопрограмм: co_await, co_yield, co_return
- Реализация простого генератора
- Асинхронные задачи и типы awaiter
- Выделение памяти для кадра сопрограммы