C++lambda表达式
捕获方式
值捕获
lambda表达式值捕获的变量在lambda函数体内部不可修改,只可读
引用捕获
lambda表达式可以引用捕获变量、const常量、constexpr常量,捕获后的属性与之间的属性一致
捕获this指针
成员函数中的lambda表达式默认不能访问成员变量,需要捕获this指针才能访问
class Foo {
public:void Show() {auto lambda = [this]() {cout << data << endl;};lambda();}
private:int data=1;
};
需要注意的是,this指针只能以值的方式进行捕获,不能以引用的方式捕获
当成员函数中存在局部变量与成员变量同名时,lambda表达式函数体内默认使用局部变量,若没有对其进行捕获,编译报错
如果指定lambda表达式中访问成员变量,可以显示使用this->data
,想要在lambda表达式中访问成员变量,需要捕获this指针,除此之外,还可以捕获*this
,效果与捕获this指针一样,通常直接捕获this即可
class Foo {
public:void Show() {auto lambda = [*this]() {cout << this->data << endl;};lambda();}
private:int data = 1;
};
C++14泛型lambda
lambda表达式的参数可以使用auto
auto lambda = [](auto x, auto y) {return x + y;
};
cout << lambda(1, 1) << endl;//2
cout << lambda(string("abc"), string("def")) << endl;//abcdef
C++20模版lambda
C++20中lambda表达式可以搭配模版使用
局部lambda对象搭配模版
局部lambda对象搭配模版使用只能进行自动推导
全局lambda对象搭配模版使用
全局lambda对象搭配模版使用必须指定模版参数
lambda表达式使用技巧
lambda表达式作为函数的返回值
class Foo {
public:auto GetLambda() {auto lambda = [this]<typename T>(T val) {data += val;AddData();cout << data << endl;};return lambda;}
private:int AddData() {return ++data;}int data = 5;
};
int main() {Foo foo;auto lambda = foo.GetLambda();lambda(3);return 0;
}
需要注意的是,访问限定符只在编译阶段发挥作用,只要编译阶段可以"骗过"编译器,main函数中的lambda就能在运行时访问AddData和data
lambda表达式递归
C++lambda表达式递归的错误写法
原因并不是没有捕获lambda,而是无法捕获lambda
想要lambda表达式实现递归,可以通过参数或者包装器完成
通过function实现lambda的递归
function<int(int)> lambda = [&lambda]<typename T>(T n) {if (n <= 2) {return n;}return lambda(n - 1) + lambda(n - 2);
};
cout << lambda(10) << endl;
通过包装器完成lambda表达式的递归时,必须以引用的方式捕获,否则可能出现错误。
通过泛型lambda实现递归
auto lambda = [](auto&& self,int n) {if (n <= 2) {return n;}return self(self,n - 1) + self(self,n - 2);
};
cout << lambda(lambda,10) << endl;
lambda表达式搭配库函数使用
lambda表达式搭配库函数使用可以自定义运算规则和比较规则
vector<int> nums = { 1,2,3,-1,8,9,-10 };
std::transform(nums.begin(), nums.end(), nums.begin(), [](int n) {return n - 3;//将nums中的每一个数-3
});
std::for_each(nums.begin(), nums.end(), [](int n) {cout << n << ' ';//打印nums中每一个数
});
cout << endl;
std::sort(nums.begin(), nums.end(), [](int l, int r) {return abs(l) < abs(r);//按照绝对值大小排序
});
std::for_each(nums.begin(), nums.end(), [](int n) {cout << n << ' ';
});