【C++】lambda 表达式
源代码:https://github.com/EricPengShuai/Interview/blob/main/c%2B%2B2.0/lambda.cpp
lambda 表达式C++11引入的,可以编写内嵌的匿名函数,代替独立函数等。在C++14中添加新特性,又加以强化。
基本语法
// 完整语法
[ capture-list ] ( params ) mutable(optional) constexpr(optional)(c++17) exception attribute -> ret { body }
// 可选的简化语法
[ capture-list ] ( params ) -> ret { body }
[ capture-list ] ( params ) { body }
[ capture-list ] { body }
参数说明:
capture-list:捕捉列表,这个不用多说,前面已经讲过,记住它不能省略;
params:参数列表,可以省略(但是后面必须紧跟函数体);
mutable:可选,将
lambda
表达式标记为mutable
后,函数体就可以修改传值方式捕获的变量;constexpr:可选,C++17,可以指定
lambda
表达式是一个常量函数;exception:可选,指定
lambda
表达式可以抛出的异常;attribute:可选,指定
lambda
表达式的特性;ret:可选,返回值类型;
body:函数执行体
常见写法
基本表达式
auto basicLambda = [] { cout << "Basic Lambda Express!" << endl; }; basicLambda();
带参数
auto add = [](int a, int b) -> int { return a + b; }; cout << add(2, 3);
捕获变量
// [] 其实就是一个闭包,用来定义捕捉模式以及变量,表示的是lambda捕捉块 int x = 10; auto add_x = [x](int a) { // 复制捕捉x,不可以修改x return a + x; }; auto multiply_x = [&x](int a) { // 引用捕捉x,可以修改x return a * x; }; cout << add_x(10) << ' ' << multiply_x(10) << endl; // mutbale 关键字可以让复制捕捉方式的表示修改参数 auto add_x_mutable = [x](int a) mutable { x *= 2; return a + x; }; cout << add_x_mutable(10) << ' ' << x << endl;
lambda 表达式禁用了辅助操作符,但是没有禁用复制构造函数
// add_x_mutable 是上面定义的 auto add_copy = add_x_mutable; cout << add_copy(10) << ' ' << x << endl;
lambda 表达式作为传递的参数
int value = 3; vector<int> v = {1, 2, 3, 5, 4, 7}; int count = count_if(v.begin(), v.end(), [value](int x) {return x > value;}); cout << count << endl; vector<int> vt(10); int a = 0; int b = 0; generate(v.begin(), v.end(), [&a, &b] { int value = b; b = b + a; a = value; }); for(auto element: vt) { cout << element << ' '; } cout << endl;
常见捕获形式
[]
:默认不捕获任何变量;[=]
:默认以值捕获所有变量;[&]
:默认以引用捕获所有变量;[x]
:仅以值捕获x,其它变量不捕获;[&x]
:仅以引用捕获x,其它变量不捕获;[=, &x]
:默认以值捕获所有变量,但是x是例外,通过引用捕获;[&, x]
:默认以引用捕获所有变量,但是x是例外,通过值捕获;[this]
:通过引用捕获当前对象(其实是复制指针);[*this]
:通过传值方式捕获当前对象;
最好不要使用 [=] [&] 捕获所有变量,可能会出现悬挂引用
新特性
捕捉表达式
int x1 = 5;
auto y = [&r = x1, x1 = x1 + 1] {
r += 2;
return x1 * x1;
};
cout << x1 << ' ' << y() << endl;
auto z = [str = "string"] {
return str;
};
cout << z() << endl;
泛型表达式
auto add1 = [](auto x, auto y) { return x + y; };
cout << add1(2, 3) << ' ' << add1(2.3, 2.3) << endl;
函数对象
for_each(vt.begin(), vt.end(), [](int x) { cout << x << ' '; });
cout << endl;