【现代C++】协程的使用

协程是C++20引入的一项重要特性,它允许函数的执行被暂停并在之后恢复,非常适合用于异步编程、数据生产者/消费者模式、状态机等场景。协程的引入旨在提供一种更简洁和直观的方式来处理异步操作和非阻塞编程。以下是C++协程的关键概念和使用示例:

1. 协程基础

在C++中,协程是通过特殊的函数实现的,这些函数可以使用co_await、co_return和co_yield关键字来暂停和恢复执行。

cpp 复制代码
#include <coroutine>
#include <iostream>
#include <future>

std::future<void> simpleCoroutine() {
    std::cout << "Hello, ";
    co_await std::suspend_always{};
    std::cout << "World!" << std::endl;
    co_return;
}

void runSimpleCoroutine() {
    auto future = simpleCoroutine();
    future.get();  // 输出:Hello, World!
}

2. 使用co_yield生成值

协程可以使用co_yield生成一系列值,非常适合实现生成器模式。

cpp 复制代码
#include <coroutine>
#include <iostream>
#include <vector>

struct Generator {
    struct promise_type {
        int current_value;
        std::suspend_always yield_value(int value) {
            current_value = value;
            return {};
        }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        Generator get_return_object() { return Generator{this}; }
        void return_void() {}
        void unhandled_exception() { std::exit(1); }
    };

    std::coroutine_handle<promise_type> coro;

    Generator(promise_type* p) : coro(std::coroutine_handle<promise_type>::from_promise(*p)) {}
    ~Generator() { if (coro) coro.destroy(); }

    int getValue() { return coro.promise().current_value; }
    bool next() { coro.resume(); return !coro.done(); }
};

Generator generateNumbers() {
    for (int i = 0; i < 5; ++i) {
        co_yield i;
    }
}

void runGenerateNumbers() {
    auto gen = generateNumbers();
    while (gen.next()) {
        std::cout << gen.getValue() << " ";
    }
    // 输出:0 1 2 3 4
}

3. 使用co_await等待异步操作

co_await表达式可以暂停当前协程的执行,直到等待的对象准备就绪。

cpp 复制代码
#include <coroutine>
#include <future>
#include <iostream>

std::future<int> asyncComputation() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return std::async(std::launch::async, []() { return 42; });
}

std::future<void> awaitCoroutine() {
    int result = co_await asyncComputation();
    std::cout << "Result: " << result << std::endl;
    co_return;
}

void runAwaitCoroutine() {
    auto future = awaitCoroutine();
    future.get();  // 输出:Result: 42
}

4. 协程与异常处理

协程支持异常处理,你可以在协程内部使用try/catch块来处理异常。

cpp 复制代码
#include <coroutine>
#include <iostream>
#include <stdexcept>

std::future<void> exceptionCoroutine() {
    try {
        throw std::runtime_error("Example exception");
        co_return;
    } catch (const std::exception& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
}

void runExceptionCoroutine() {
    auto future = exceptionCoroutine();
    future.get();  // 输出:Caught exception: Example exception
}

通过这些示例可以看到C++协程如何用于不同的场景,它们提供了一种更直观和简洁的方式来处理异步操作、生成数据和编写复杂的控制流逻辑。

相关推荐
-Marks-3 分钟前
【C++编程】STL容器(二)--- vector底层模拟实现(常用接口实现 | 扩容机制 | 深浅拷贝 | 迭代器失效)
开发语言·c++·vector·内存管理·迭代器失效·vector底层模拟实现
Shadow(⊙o⊙)20 分钟前
C++11并发支持库
开发语言·c++
一技安身21 分钟前
【java】JDK8 + JDK17 绿色解压共存方案-全程不修改任何系统环境变量
java·开发语言
ShineWinsu32 分钟前
对于Redis:主从复制的解析
linux·数据库·c++·redis·缓存·面试·主从复制
hudd6681 小时前
JavaEE 初阶 - 多线程(初阶)
java·开发语言·java-ee
I Am a robert girl1 小时前
稀有事件估计的迭代去对齐:从源码视角拆解重要性采样新范式
开发语言·python·机器学习·重要性采样·蒙特卡洛方法·稀有事件估计
无忧.芙桃2 小时前
C++ 并查集详解:原理、实现与应用
c语言·c++·算法·leetcode
golang学习记2 小时前
rust开发,选VS Code还是RustRover?
开发语言·后端·rust
打工仔折腾 AI2 小时前
从零写一个CAD 05:以鼠标为中心的滚轮缩放,招法能复用但顺序不能反
开发语言·后端·python·性能优化·计算机外设·swift·ai agent 实战
CarIise2 小时前
Java实训阶段查漏补缺复习笔记1
java·开发语言·笔记