Lambda 表达式是 C++11 引入的匿名函数(没有名字的临时函数),主要用于简化代码、就地定义短小函数、配合算法 / 回调使用,是现代 C++ 开发必备语法。
一、基础语法
1.完整语法格式
[捕获列表] (参数列表) -> 返回值类型 { 函数体 };
极简记忆版:
- [] 捕获列表:必写,用来 “抓取” 外部变量供函数体使用
- () 参数列表:可选,和普通函数参数一样
- -> type 返回值:可选,编译器能自动推导时可省略
- {} 函数体:必写,存放执行逻辑
2.省略写法
从右向左依次省略,只有省略返回值类型才能省略参数列表
二、核心用法
1. 无参无捕获
不需要外部变量,也没有参数:
#include <iostream>
using namespace std;
int main() {
// 定义并直接调用 Lambda
[]() { cout << "Hello Lambda!" << endl; }();
// 赋值给变量,后续调用
auto func = [] { cout << "无参简化版" << endl; };
func();
return 0;
}
2. 带参数
// 计算两数之和
auto add = [](int a, int b) { return a + b; };
cout << add(3, 5) << endl; // 输出 8
3.带返回值
- 简单逻辑:编译器自动推导返回值,不用写 ->
- 复杂逻辑:建议显式声明(更清晰)
// 自动推导
auto max = [](int a, int b) { return a > b ? a : b; };
// 显式声明返回值 int
auto sum = [](double a, double b) -> int { return a + b; };
三、捕获列表 []
全局变量,静态成员不存在捕获概念,若 Lambda 内部有同名局部变量 / 形参,内部变量优先(局部遮蔽全局)。
局部变量、函数形参存在捕获概念;Lambda 只能捕获:与 Lambda 同作用域、且在 Lambda 定义语句之前声明的变量。
如果调用两次,捕获列表只在定义时参与运算,只进行一次
#include <iostream>
using namespace std;
// 全局变量:无捕获概念
int num = 100;
void test(int param) // param:函数形参,存在捕获概念
{
// 局部变量:存在捕获概念,定义在lambda之前
int local1 = 200;
// Lambda定义处:只能捕获同作用域、定义前的局部/形参
auto lambda = [param, local1]() {
// 1. 内部定义同名局部变量,遮蔽全局num
int num = 999;
cout << "Lambda内部同名num:" << num << endl; // 输出999,内部优先,遮蔽全局
// 2. 捕获到的形参、局部变量正常使用
cout << "捕获的形参param:" << param << endl;
cout << "捕获的局部local1:" << local1 << endl;
};
// 定义在Lambda之后的局部变量:不能被捕获
int local2 = 300;
// auto err = [local2](){}; // 编译报错:local2在lambda定义后,无法捕获
lambda();
}
int main()
{
test(50);
return 0;
}
1.值捕获 [=] [x]
用了才会建立副本,相当于创建副本,Lambda 内部用的是拷贝,和外部变量无关。
值捕获完只可读,不可写
去常性:
auto lam = [a]() mutable {
a = 100; // 成功
};
-
加 mutable 改的是副本
-
外面的
a依然不变 -
引用捕获
[&a]不用加 mutable,本来就能改
2.引用捕获 [&] [&x]
不创建副本,直接用外部变量本身。
可读,可改
3.析构顺序
值捕获:拷贝入栈按书写顺序,析构逆序;
引用捕获:不入栈、不析构,跟随外部变量。
4.捕获格式(8种)
| 格式 | 含义 |
|---|---|
[] | 不捕获任何变量 |
[x] | 值捕获 x(拷贝副本,默认 const 只读) |
[&x] | 引用捕获 x(直接用原变量,可修改) |
[=] | 全部值捕获:当前作用域所有局部 / 形参都值捕获 |
[&] | 全部引用捕获:当前作用域所有局部 / 形参都引用捕获 |
[=, &x] | 默认全部值捕获,唯独 x 引用捕获 |
[&, x] | 默认全部引用捕获,唯独 x 值捕获 |
[this] | 捕获类的 this 指针,访问类成员 |
四、泛型捕获
这是 C++14 最重要的 Lambda 升级之一
1.核心格式
[变量名 = auto 表达式]
作用:在捕获列表里,让编译器自动推导捕获变量的类型,和普通 auto 一样。
五、类的成员捕获
异类对象可捕获,异类成员不可捕;
本类成员靠 this,访问必须走对象。
1.核心总规则
成员变量 / 成员函数,不能直接捕获(不能写 [m_val])
只能捕获两种:
[this]:捕获对象指针,操作原对象(C++11 起)
[*this]:捕获整个对象副本,操作副本(C++17 起)
函数内局部变量、形参正常捕获;全局变量不用捕获
#include <iostream>
using namespace std;
// 另一个类
class B {
public:
int b_val = 200;
};
// 本类
class A {
public:
int a_val = 100;
// 形参是另一个类B的对象
void func(B b_obj, B& b_ref)
{
int x = 10;
// 捕获:this(本类)、b_obj(另一个类值捕获)、b_ref(另一个类引用捕获)、x(局部)
auto lam = [this, b_obj, &b_ref, x]() mutable {
// 访问本类成员
a_val = 111;
// 访问另一个类B的成员(必须通过对象)
b_obj.b_val = 222; // 修改副本
b_ref.b_val = 333; // 修改原B对象
// 错误:不能直接捕获另一个类的成员
// auto err = [b_obj.b_val](){};
};
lam();
cout << "本类A:" << a_val << endl;
cout << "另一个类B原对象:" << b_ref.b_val << endl;
}
};
int main()
{
A a;
B b;
a.func(b, b);
return 0;
}
2560

被折叠的 条评论
为什么被折叠?



