C++11 lambda表达式

概念

  • 本质 = 编译器自动生成的 匿名函数对象(仿函数)
  • 可以定义在函数内部(普通函数不行)
  • 没有可写出来的类型名 → 必须用 auto 接收

例子:

cpp 复制代码
auto func = [](){ cout << "hello"; };

lambda表达式格式

cpp 复制代码
[捕获列表] (参数) -> 返回值 { 函数体 }
  1. [] 捕获列表

    • 捕获外部变量给 lambda 用
    • 不能为空 ,哪怕不捕获也要写 []------必写
    • 捕获方式:
      • [=] 值捕获
      • [&] 引用捕获
      • [x, &y] 单独捕获
  2. (参数)

    • 和普通函数参数一样
    • 没有参数可以省略 ()
  3. -> 返回值

    • 返回值明确时 可以省略
    • 无返回值也可以省略
  4. { 函数体 }

    • 和普通函数逻辑一样
    • 不能为空 ,至少写 {}------必写

3. 最简单的 4 种写法(一看就会)

  1. 无参无返
cpp 复制代码
[]{};
  1. 有参
cpp 复制代码
[](int a, int b){ return a+b; };
  1. 有返回值(可省略->)
cpp 复制代码
[](int a)->int{ return a*2; };
  1. 捕获外部变量
cpp 复制代码
int x = 10;
auto f = [x](){ cout << x; };

捕捉列表

为什么需要捕捉?

Lambda 默认只能访问自身参数和函数体内变量 ,要使用外层作用域变量 ,必须在 [] 里声明捕捉。

三种捕捉方式

1. 显式捕捉(手动指定变量)

  • 语法:[变量名, &变量名, ...]
  • 含义:
    • [x, y]:x、y 为值捕捉(拷贝一份,lambda 内是副本)
    • [&z]:z 为引用捕捉(直接用原变量,修改会影响外部)
  • 例子:[x, y, &z] → x、y 值捕捉,z 引用捕捉

2. 隐式捕捉(自动识别变量)

  • 语法:
    • [=]隐式值捕捉 → 编译器自动捕捉 lambda 中用到的所有外层变量,全部按值传递
    • [&]隐式引用捕捉 → 编译器自动捕捉 lambda 中用到的所有外层变量,全部按引用传递

3. 混合捕捉(显式 + 隐式结合)

  • 语法规则:
    • 第一个元素必须是 =&
    • [=, &x]:其余变量隐式值捕捉,x 单独引用捕捉
      例子:[&, x, y]:其余变量隐式引用捕捉,x、y 单独值捕捉
  • 注意:
    • = 开头时,后面只能跟引用捕捉的变量
    • & 开头时,后面只能跟值捕捉的变量

捕捉范围与特殊变量

  • 局部域 lambda :只能捕捉 lambda 定义之前的局部变量
  • 静态局部变量 / 全局变量不需要捕捉,可以直接在 lambda 里使用
  • 全局 lambda :定义在全局作用域时,捕捉列表必须为空(没有可捕捉的局部变量)

关于const 与 mutable 修饰

  • 默认:值捕捉的变量在 lambda 内是 const 的,不能修改
  • mutable 修饰:
    • 放在参数列表后:[x]() mutable { x++; }
    • 作用:取消值捕捉变量的 const 性,允许在 lambda 内修改
    • 注意:修改的是副本 ,不会影响外部原变量;且参数列表 () 不能省略(即使无参)

lambda原理

本质:编译器生成的仿函数对象

  • Lambda 本身是语法糖,编译后会被转换成一个匿名仿函数类 (重载了 operator() 的类)。
  • 从汇编/机器码层面看,不存在"lambda"这个概念,只有普通的类和函数调用。
  • 这一点和范围 for 很像:范围 for 底层是迭代器,而 lambda 底层是仿函数。

仿函数类的结构映射

Lambda 语法部分 对应仿函数类的结构
捕捉列表 [x, &y] 类的成员变量 (值捕捉 → 成员变量拷贝;引用捕捉 → 成员变量是引用)
参数列表 (int a) operator() 的参数列表
返回值 -> int operator() 的返回值类型
函数体 { ... } operator() 的函数实现

类名与唯一性

  • 编译器会为每个 lambda 生成一个独一无二的类名(按内部规则生成,开发者无法直接写出)。
  • 不同的 lambda(即使签名完全一样)也会生成不同的类,因此 lambda 没有可显式书写的类型,只能用 auto 或模板参数接收。
相关推荐
NiceCloud喜云3 小时前
Opus 4.8 的 Effort Control 怎么选:Low 到 Max 五档策略
android·java·大数据·前端·c++·python·spring
cjhbachelor3 小时前
c++继承
c++
AI玫瑰助手3 小时前
Python函数:默认参数的定义与注意事项
开发语言·python·信息可视化
油炸自行车3 小时前
Claude Code 错误:API Error: 400 Failed to deserialize the JSON body into the
开发语言·javascript·json·trae·claude code·api error 400
肩上风骋4 小时前
C++14特性
开发语言·c++·c++14特性
JAVA社区5 小时前
Java高级全套教程(十)—— SpringCloudAlibaba超详细实战详解
java·开发语言·spring cloud·面试·职场和发展
弥树子5 小时前
踩坑记录:服务器内网调用接口,真实请求URL与官方公开URL不一致问题排查
开发语言·php
z落落5 小时前
C# ToCharArray + foreach遍历 + String与StringBuilder
开发语言·c#
学代码的真由酱6 小时前
Java多用户一对一网页聊天室-测试报告
java·开发语言·功能测试·测试
人道领域6 小时前
【LeetCode刷题日记】669.修剪二叉搜索树
开发语言·python·算法