C++ C++  ·  30 вопросов  ·  ~85 мин  ·  ⏱ Таймер 25:00  ·  Сложный  · 

Корутины C++

Профессиональный тест разбирает корутину как преобразованную компилятором машину состояний. Вопросы охватывают promise_type, awaiter-протокол, время жизни coroutine frame, отмену и композицию задач — без упрощения “co_await просто ждёт”.

Отвечено: 0 из 30
⏱ --:--
0%
💡 Инструкция: Выберите один ответ из пяти. В тесте 30 вопросов, время — 85 минут. Во многих заданиях недостаточно узнать конструкцию: проследите порядок вычислений, время жизни объектов, владение ресурсами и условия, при которых решение остаётся корректным. После завершения откроются правильные ответы, объяснения, общий результат и тематические шкалы.
Вопрос 1 из 30
Как компилятор находит promise_type корутины?
C++C++20
struct Task {
    struct promise_type {
        Task get_return_object();
        std::suspend_never initial_suspend() noexcept;
        std::suspend_always final_suspend() noexcept;
        void return_void();
        void unhandled_exception();
    };
};
Task run(int id);
Вопрос 2 из 30
Для чего вызывается `get_return_object()`?
C++C++20
struct Task {
    struct promise_type {
        Task get_return_object() {
            return Task{std::coroutine_handle<promise_type>::from_promise(*this)};
        }
        // ...
    };
    std::coroutine_handle<promise_type> handle;
};
Вопрос 3 из 30
Что определяет `initial_suspend()`?
C++C++20
struct promise_type {
    std::suspend_always initial_suspend() noexcept { return {}; }
    std::suspend_always final_suspend() noexcept { return {}; }
    // ...
};

Task job = run(); // начнёт ли тело выполняться сразу?
Вопрос 4 из 30
Зачем `unhandled_exception()` в promise?
C++C++20
struct promise_type {
    std::exception_ptr error;

    void unhandled_exception() noexcept {
        error = std::current_exception();
    }
};
Вопрос 5 из 30
Что делает `return_value(v)` или `return_void()`?
C++C++20
struct promise_type {
    std::optional<int> result;

    void return_value(int value) noexcept {
        result = value;
    }
};

Task<int> answer() { co_return 42; }
Вопрос 6 из 30
В каком порядке вызываются основные методы awaiter?
C++C++20
struct Awaiter {
    bool await_ready() const noexcept;
    void await_suspend(std::coroutine_handle<> h);
    int await_resume();
};

int value = co_await Awaiter{};
Вопрос 7 из 30
Что означает `await_ready() == true`?
C++C++20
struct CachedValue {
    int value;
    bool await_ready() const noexcept { return true; }
    void await_suspend(std::coroutine_handle<>) noexcept;
    int await_resume() const noexcept { return value; }
};

int x = co_await CachedValue{42};
Вопрос 8 из 30
Что получает `await_suspend(std::coroutine_handle<> h)`?
C++C++20
struct TimerAwaiter {
    std::chrono::milliseconds delay;
    bool await_ready() const noexcept { return false; }
    void await_suspend(std::coroutine_handle<> continuation);
    void await_resume() const noexcept {}
};
Вопрос 9 из 30
Что означает возврат bool из await_suspend?
C++C++20
struct Awaiter {
    bool await_ready() const noexcept { return false; }
    bool await_suspend(std::coroutine_handle<> h) {
        return schedule_or_continue(h);
    }
    Result await_resume();
};
Вопрос 10 из 30
Как `operator co_await` участвует в протоколе?
C++C++20
struct SocketRead {
    Socket& socket;
    auto operator co_await() & {
        return ReadAwaiter{socket};
    }
};

std::size_t n = co_await request.read_operation();
Вопрос 11 из 30
Где обычно хранятся локальные переменные, переживающие suspension point?
C++C++20
Task parse(Stream& stream) {
    Buffer buffer = co_await stream.read();
    auto header = parse_header(buffer);
    co_await validate(header);
    co_return;
}
Вопрос 12 из 30
Кто обязан вызвать `handle.destroy()` для вручную управляемой корутины?
C++C++20
class Generator {
public:
    ~Generator() {
        if (handle_) handle_.destroy();
    }
    Generator(Generator&& other) noexcept
        : handle_(std::exchange(other.handle_, {})) {}
private:
    std::coroutine_handle<promise_type> handle_;
};
Вопрос 13 из 30
Почему `final_suspend()` часто возвращает suspend_always?
C++C++20
struct promise_type {
    std::suspend_always final_suspend() noexcept { return {}; }
    void return_void() noexcept {}
    void unhandled_exception() { std::terminate(); }
};

// Владелец handle читает результат и затем вызывает destroy().
Вопрос 14 из 30
Что опасно в корутине, принимающей `const std::string&` и приостанавливающейся?
C++C++20
Task log_later(const std::string& text) {
    co_await schedule_on(worker_pool);
    write_log(text); // ссылка может пережить аргумент вызова
}

log_later(std::string("temporary"));
Вопрос 15 из 30
Можно ли вызывать resume на already-done coroutine handle?
C++C++20
void resume_if_needed(std::coroutine_handle<> h) {
    if (h && !h.done()) {
        h.resume();
    }
}
Вопрос 16 из 30
Как task B обычно возвращает управление ожидающей корутине A?
C++C++20
struct FinalAwaiter {
    bool await_ready() const noexcept { return false; }
    std::coroutine_handle<> await_suspend(
        std::coroutine_handle<promise_type> h
    ) const noexcept {
        return h.promise().continuation;
    }
    void await_resume() const noexcept {}
};
Вопрос 17 из 30
Что такое symmetric transfer?
C++C++20
std::coroutine_handle<> await_suspend(
    std::coroutine_handle<> awaiting
) noexcept {
    continuation = awaiting;
    return child_handle; // передача выполнения другой корутине
}
Вопрос 18 из 30
Чем generator отличается от task?
C++C++20
Generator<int> numbers() {
    for (int i = 0; i < 3; ++i)
        co_yield i;
}

Task<int> answer() {
    co_return 42;
}
Вопрос 19 из 30
Как обычно распространяется исключение из awaited task?
Вопрос 20 из 30
Почему смешение eager и lazy tasks может давать неожиданный порядок побочных эффектов?
Вопрос 21 из 30
Как проверить отсутствие утечки coroutine frame?
Вопрос 22 из 30
Как воспроизвести гонку двойного resume?
Вопрос 23 из 30
Что тестировать у отменяемой корутины?
Вопрос 24 из 30
Как обнаружить ссылку на уничтоженный аргумент в frame?
Вопрос 25 из 30
Почему breakpoint на строке с co_await иногда недостаточен?
Вопрос 26 из 30
Всегда ли coroutine frame выделяется в куче?
Вопрос 27 из 30
Что такое backpressure для coroutine pipeline?
Вопрос 28 из 30
Почему API должен документировать, на каком executor продолжится код после co_await?
Вопрос 29 из 30
Какой риск у task, который начинает работу, но его return object можно молча отбросить?
Вопрос 30 из 30
Когда callback может быть лучше пользовательской корутины?

Ответьте на все 30 вопросов, чтобы получить результат

🔗 Встроить тест на свой сайт (iframe) ▼

Скопируйте код и вставьте в любое место на вашем сайте:

Также доступна прямая ссылка на embed-страницу