> 技术文档 > Lambda 捕获方式

Lambda 捕获方式


一、Lambda 捕获列表的几种捕获方式

  1. 值捕获(by value)
    捕获外部变量的当前值,lambda 内部保存的是变量的副本。
    语法示例:

    int x = 10;auto f = [x]() { return x + 1; };
  2. 引用捕获(by reference)
    捕获变量的引用,lambda 内部直接访问外部变量本体。
    语法示例:

    int x = 10;auto f = [&x]() { x++; };
  3. 隐式捕获

    • [=]:隐式按值捕获所有用到的外部变量
    • [&]:隐式按引用捕获所有用到的外部变量
  4. 混合捕获
    可以在捕获列表中混合指定,比如:

    int x = 1, y = 2;auto f = [x, &y]() { return x + y; };
  5. 移动捕获(C++14 起)
    使用初始化捕获将变量移动进 lambda,语法:

    std::unique_ptr<int> p = std::make_unique<int>(10);auto f = [ptr = std::move(p)]() { return *ptr; };

二、引用捕获需要注意什么?

  1. 生命周期风险

    • 捕获的是外部变量的引用,如果外部变量在 lambda 调用时已经销毁,引用变成悬空,访问会导致未定义行为。
    • 例如捕获局部变量的引用,但 lambda 在变量作用域外执行(如异步调用或延迟执行),就会出错。
  2. 修改外部变量

    • 引用捕获允许修改外部变量(前提变量非 const)。

    • 例如:

      int x = 10;auto f = [&x]() { x = 20; };f();std::cout << x; // 输出 20
  3. 线程安全问题

    • 引用捕获多个线程访问时,可能存在数据竞争,需要同步保护。
  4. 不能捕获临时对象的引用

    • 引用捕获不能捕获即将销毁的临时变量引用。

三、总结

捕获方式 说明 适用场景 值捕获 [x] 复制外部变量,lambda 内部独立 需要变量快照,防止外部修改影响 引用捕获 [&x] 捕获变量引用,访问的是外部变量本体 需要修改外部变量,或变量较大避免复制 隐式捕获 [=] 按值捕获所有外部变量 简单只读场景 隐式捕获 [&] 按引用捕获所有外部变量 需要修改或大对象避免复制 移动捕获 C++14起支持,移动对象所有权到lambda内 管理资源(unique_ptr等)