卡码笔记
首页
计算机基础
C++
Java
面经
笔记广场 (opens new window)
代码随想录 (opens new window)
首页
计算机基础
C++
Java
面经
笔记广场 (opens new window)
代码随想录 (opens new window)
  • 基础与语法

  • 面向对象

  • STL 与容器

  • 内存管理

  • C++11 与现代 C++

    • C++11中的新特性有哪些
    • C++11中的多线程编程
    • 左值引用和右值引用的区别
    • 移动语义有什么作用,原理是什么
    • 完美转发的作用及实现
    • 说一下c++中stdmove与stdforward的区别
    • 说一下lambda函数
    • 仿函数与lambda性能对比
    • c++中 STL中仿函数与lambda表达式的性能对比
    • C++中的RAII机制
    • C++中的异常处理机制
    • C++中的协程概念及实现
      • 简要回答
      • 详细回答
      • 代码示例
      • 知识拓展
  • 智能指针

  • 并发与 I/O

# 面试时没有回答好问题是很正常的,被面试官质疑时,要有今天不会明天会的底气,面后做好复盘,不在同一道题目上跌倒第二次,今天就从 C++中的协程概念及实现 背起来

C++中的协程概念及实现

# 简要回答

C++20引入了协程作为语言级别的异步编程支持。

协程是能够暂停执行并在之后恢复的函数,通过co_await、co_yield、co_return关键字实现。

它包含promise对象、coroutine handle和awaiter三个核心组件,提供比回调更简洁的异步代码编写方式。

# 详细回答

协程核心概念:

协程函数:包含co_await、co_yield、co_return的函数 Promise对象是指控制协程生命周期和返回值

Coroutine Handle被用于恢复或销毁协程的句柄

Awaiter通常定义co_await表达式的等待行为

协程的执行过程:

第一分配协程帧(存储局部变量和状态),第二创建promise对象,第三调用promise.get_return_object()获取返回给调用者的对象,第四执行协程体直到暂停或结束,第五通过handle恢复执行或销毁资源

# 代码示例

#include <iostream>
#include <coroutine>
#include <thread>
#include <chrono>

// 简单的生成器协程
struct Generator {
    struct promise_type {
        int 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 unhandled_exception() { std::terminate(); }

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

    std::coroutine_handle<promise_type> handle;

    explicit Generator(std::coroutine_handle<promise_type> h) : handle(h) {}
    ~Generator() { if (handle) handle.destroy(); }

    int value() { return handle.promise().current_value; }
    bool move_next() {
        if (!handle.done()) {
            handle.resume();
            return !handle.done();
        }
        return false;
    }
};

Generator range(int start, int end) {
    for (int i = start; i <= end; ++i) {
        co_yield i;  // 每次yield一个值并暂停
    }
}

// 异步任务示例
struct AsyncTask {
    struct promise_type {
        int result;

        AsyncTask get_return_object() {
            return AsyncTask{std::coroutine_handle<promise_type>::from_promise(*this)};
        }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void unhandled_exception() { std::terminate(); }
        void return_value(int value) { result = value; }
    };

    std::coroutine_handle<promise_type> handle;

    struct Awaiter {
        bool await_ready() { return false; }
        void await_suspend(std::coroutine_handle<> h) {
            std::thread([h]() {
                std::this_thread::sleep_for(std::chrono::seconds(1));
                h.resume();
            }).detach();
        }
        void await_resume() {}
    };

    Awaiter operator co_await() {
        return Awaiter{};
    }
};

AsyncTask async_work() {
    std::cout << "开始异步工作..." << std::endl;
    co_await AsyncTask::Awaiter{};
    std::cout << "异步工作完成!" << std::endl;
    co_return 42;
}

int main() {
    // 生成器示例
    auto gen = range(1, 5);
    while (gen.move_next()) {
        std::cout << "生成值: " << gen.value() << std::endl;
    }

    // 异步任务示例
    auto task = async_work();
    std::this_thread::sleep_for(std::chrono::seconds(2));

    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

# 知识拓展

  • 协程vs线程

线程:是操作系统调度,真正的并行过程,并且上下文切换的成本比较高

协程:是用户态调度,同于协作式多任务,它的切换成本极低

  • 协程vs回调

回调:容易产生回调地狱,错误处理复杂

协程:线性代码风格,异常处理自然

  • 知识图解

image

  • 适用场景

异步I/O操作:网络请求、文件读写

生成器:大数据集流式处理

状态机:复杂状态转换逻辑

游戏开发:角色行为、动画序列

GUI编程:保持UI响应的后台任务

  • 面试官很能追问

Q1: 协程和线程的主要区别是什么?

A1: 线程是操作系统级别的并发单位,由内核调度,支持真正并行但上下文切换成本高。协程是用户态的轻量级线程,由程序自己调度,切换成本低但不支持真正并行。

Q2: 协程帧通常包含哪些内容?

A2: 协程帧包含:promise对象、函数参数、局部变量、恢复点信息、挂起时寄存器状态等。它本质上是一个保存协程执行状态的堆分配对象。

Q3: co_await表达式的三阶段流程?

A3:

await_ready:检查是否可以直接返回结果

await_suspend:挂起协程,安排恢复时机

await_resume:恢复时获取结果或继续执行

Q4: 如何避免协程的内存泄漏?

A4: 确保coroutine_handle正确销毁:使用RAII包装器、在final_suspend中适当处理、避免循环引用。推荐使用智能指针管理协程生命周期。

Last Updated: 3/10/2026, 6:08:48 PM

← C++中的异常处理机制 什么是智能指针,C++中有哪几种智能指针 →

评论

验证登录状态...

侧边栏
夜间
卡码简历
代码随想录
卡码投递表🔥
2026群
添加客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记
鼓励/支持/赞赏Carl
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪