lambda表达式
lambda 表达式定义了一个匿名函数,并且可以捕获一定范围内的变量。lambda 表达式的语法形式可简单归纳如下:
[ capture ] ( params ) opt -> ret { body; };
其中 capture 是捕获列表,params 是参数表,opt 是函数选项,ret 是返回值类型,body是函数体。
因此,一个完整的 lambda 表达式看起来像这样:
auto f = [](int a) -> int { return a + 1; }; std::cout << f(1) << std::endl; // 输出: 2
其实很多时候,lambda 表达式的返回值是非常明显的,比如这个例子。因此,C++11 中允许省略 lambda 表达式的返回值定义:
需要注意的是,初始化列表不能用于返回值的自动推导:
auto x1 = [](int i){ return i; }; // OK: return type is int auto x2 = [](){ return { 1, 2 }; }; // error: 无法推导出返回值类型
这时我们需要显式给出具体的返回值类型。
另外,lambda 表达式在没有参数列表时,参数列表是可以省略的。因此像下面的写法都是正确的:
auto f1 = [](){ return 1; }; auto f2 = []{ return 1; }; // 省略空参数表
lambda 表达式还可以通过捕获列表捕获一定范围内的变量:
- [] 不捕获任何变量。
- [&] 捕获外部作用域中所有变量,并作为引用在函数体中使用(按引用捕获)。
- [=] 捕获外部作用域中所有变量,并作为副本在函数体中使用(按值捕获)。
- [=,&foo] 按值捕获外部作用域中所有变量,并按引用捕获 foo 变量。
- [bar] 按值捕获 bar 变量,同时不捕获其他变量。
-
[this] 捕获当前类中的 this 指针,让 lambda 表达式拥有和当前类成员函数同样的访问权限。如果已经使用了 & 或者 =,就默认添加此选项。捕获 this 的目的是可以在 lamda 中使用当前类的成员函数和成员变量。
class A { public: int i_ = 0; void func(int x, int y) { auto x1 = []{ return i_; }; // error,没有捕获外部变量 auto x2 = [=]{ return i_ + x + y; }; // OK,捕获所有外部变量 auto x3 = [&]{ return i_ + x + y; }; // OK,捕获所有外部变量 auto x4 = [this]{ return i_; }; // OK,捕获this指针 auto x5 = [this]{ return i_ + x + y; }; // error,没有捕获x、y auto x6 = [this, x, y]{ return i_ + x + y; }; // OK,捕获this指针、x、y auto x7 = [this]{ return i_++; }; // OK,捕获this指针,并修改成员的值 } }; int a = 0, b = 1; auto f1 = []{ return a; }; // error,没有捕获外部变量 auto f2 = [&]{ return a++; }; // OK,捕获所有外部变量,并对a执行自加运算 auto f3 = [=]{ return a; }; // OK,捕获所有外部变量,并返回a auto f4 = [=]{ return a++; }; // error,a是以复制方式捕获的,无法修改 auto f5 = [a]{ return a + b; }; // error,没有捕获变量b auto f6 = [a, &b]{ return a + (b++); }; // OK,捕获a和b的引用,并对b做自加运算 auto f7 = [=, &b]{ return a + (b++); }; // OK,捕获所有外部变量和b的引用,并对b做自加运算
在这个例子中,lambda 表达式按值捕获了所有外部变量。在捕获的一瞬间,a 的值就已经被复制到f中了。之后 a 被修改,但此时 f 中存储的 a 仍然还是捕获时的值,因此,最终输出结果是 0。
如果希望 lambda 表达式在调用时能够即时访问外部变量,我们应当使用引用方式捕获。
从上面的例子中我们知道,按值捕获得到的外部变量值是在 lambda 表达式定义时的值。此时所有外部变量均被复制了一份存储在 lambda 表达式变量中。此时虽然修改 lambda 表达式中的这些外部变量并不会真正影响到外部,我们却仍然无法修改它们。 -
int a = 0; auto f1 = [=]{ return a++; }; // error,修改按值捕获的外部变量 auto f2 = [=]() mutable { return a++; }; // OK,mutable
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现