TypechoJoeTheme

至尊技术网

统计
登录
用户名
密码
文章目录

C++协程基础与生成器实现

2025-11-15
/
0 评论
/
2 阅读
/
正在检测是否收录...
11/15

在现代C++开发中,协程(Coroutine)作为一种轻量级的并发编程模型,正逐渐被开发者所重视。尤其是在需要延迟计算、逐个产生数据的场景下,生成器(Generator)模式显得尤为实用。本文将带你从零开始,使用C++20标准中的协程特性,实现一个简单的生成器,并深入理解其背后的工作机制。

传统的函数一旦返回,其执行上下文就会被销毁,无法再次从中断处继续执行。而协程则不同,它可以在运行过程中通过co_yield暂停自身,保留当前的状态,待下一次调用时从中断点恢复执行。这种能力使得协程非常适合用于实现惰性求值的数据流,比如无限序列、大文件逐行读取或网络数据流处理等。

要实现一个生成器,首先我们需要定义一个符合协程规范的返回类型。这个类型必须包含一个名为promise_type的嵌套类型,它是协程状态管理的核心。我们以一个返回整数的生成器为例:

cpp

include

include

struct Generator {
struct promisetype { int currentvalue;

    std::suspend_always initial_suspend() { return {}; }
    std::suspend_always final_suspend() noexcept { return {}; }
    Generator get_return_object() { return Generator{this}; }

    void return_void() {}
    std::suspend_always yield_value(int value) {
        current_value = value;
        return {};
    }

    void unhandled_exception() { std::terminate(); }
};

using handle_type = std::coroutine_handle<promise_type>;

explicit Generator(promise_type* p)
    : coro(handle_type::from_promise(*p)) {}

~Generator() {
    if (coro) coro.destroy();
}

Generator(const Generator&) = delete;
Generator& operator=(const Generator&) = delete;

Generator(Generator&& other) noexcept
    : coro(other.coro) {
    other.coro = nullptr;
}

Generator& operator=(Generator&& other) noexcept {
    if (this != &other) {
        if (coro) coro.destroy();
        coro = other.coro;
        other.coro = nullptr;
    }
    return *this;
}

int value() const { return coro.promise().current_value; }

bool move_next() {
    if (!coro || coro.done()) return false;
    coro.resume();
    return !coro.done();
}

private:
handle_type coro;
};

上述代码中,promise_type定义了协程的行为:yield_value在每次调用co_yield时被触发,保存当前值并挂起;get_return_object返回供外部使用的生成器对象;而initial_suspendfinal_suspend控制协程启动和结束时是否挂起。

接下来,我们可以编写一个使用该生成器的函数,例如生成斐波那契数列:

cpp Generator fibonacci() { int a = 0, b = 1; while (true) { co_yield a; int next = a + b; a = b; b = next; } }

使用方式非常直观:

cpp int main() { auto gen = fibonacci(); for (int i = 0; i < 10; ++i) { if (gen.move_next()) { std::cout << gen.value() << " "; } } std::cout << std::endl; return 0; }

输出结果为:0 1 1 2 3 5 8 13 21 34

整个过程无需预计算所有值,而是按需生成,节省内存且响应迅速。这正是生成器的魅力所在。

值得注意的是,C++20的协程是无栈协程(stackless coroutine),这意味着它们不能在任意嵌套层级中挂起,只能在最外层的协程函数中使用co_yieldco_await等关键字。但这也带来了更高的性能和更低的开销。

此外,生成器对象的生命周期管理至关重要。由于协程状态由堆上分配的帧维护,我们必须确保在不再需要时正确销毁句柄,避免资源泄漏。上面的移动语义设计正是为此服务。

总结来说,C++20协程为实现高效、优雅的生成器提供了语言级别的支持。通过合理设计promise_type和协程句柄的封装,我们可以轻松构建出功能强大且易于使用的惰性序列生成工具。随着编译器对协程支持的日益成熟,这类技术将在实际项目中发挥越来越重要的作用。

生成器异步编程GeneratorC++20协程co_yield协程实现
朗读
赞(0)
版权属于:

至尊技术网

本文链接:

https://www.zzwws.cn/archives/38647/(转载时请注明本文出处及文章链接)

评论 (0)

人生倒计时

今日已经过去小时
这周已经过去
本月已经过去
今年已经过去个月

最新回复

  1. 强强强
    2025-04-07
  2. jesse
    2025-01-16
  3. sowxkkxwwk
    2024-11-20
  4. zpzscldkea
    2024-11-20
  5. bruvoaaiju
    2024-11-14

标签云