前言
- lambda表达式时C++11时引入的特性
- lambda又称匿名函数
- lambda本质是一个特殊的,匿名的类类型。它是一个带有operator()的类,即仿函数。
- 仿函数(functor), 就是使得一个类的使用看上去像一个函数。其实现为类中实现一个operator(), 这个类就有了类似函数的行为,即为一个仿函数类。
lambda表达式的基本用法
[capture] (params) -> ret {body;};
- capture 捕获列表
- params 参数表
- ret 返回值类型
- body 函数体
捕获列表
- []: 表示不捕获任何变量
- [=]: 表示按值捕获变量
- [&]: 表示按引用捕获变量
使用场景
函数体比较简单,由于作用域有限,最好是不在别的地方调用,这种场景下使用lambda可以省去函数的声明。
实验01 overload() to implement lambda
#include <iostream>
class AddNum {
public:
AddNum(int num): num_(num) {};
// int addNum(int x) const {
// return num_ + x;
// }
int operator()(int x) const {
return num_ + x;
}
private:
int num_;
};
int main()
{
/* functor */
auto add_num = AddNum(10);
/* auto x = add_num.addNum(5); */
auto x = add_num(5);
std::cout << "x: " << x << std::endl;
/* lambda [] 中是 lambda的捕获列表 */
/* lambda_num变量的作用域仅限于lambda表达式 */
auto add_num2 = [lambda_num = 10](int x) {
return lambda_num + x;
};
auto lambda_x = add_num2(5);
std::cout << "lambda_x: " << lambda_x << std::endl;
}
编译并运行:
g++ lambda_01.cpp -std=c++17 && ./a.out
x: 15
lambda_x: 15
可以看到下方的lambda表达式所实现的效果与AddNum类重载()运算符后的效果相同。
实验02 store lambda to func
#include <iostream>
int main() {
/* example 1 */
int res = [](int x)->int {
return ++x;
}(3);
std::cout << "res: " << res << std::endl;
/* example 2, store it to func */
/* we can use auto replace std::function */
/* old: std::function<int(int)> func = [](int x)->int { */
/* we can del retuen type int */
/* old: auto func = [](int x)->int { */
auto func = [](int x) {
return ++x;
};
std::cout<<"i:";
for (int i = 0; i < 10; i++) {
std::cout << " " << func(i);
}
std::cout<<std::endl;
}
编译运行:
g++ lambda_02.cpp -std=c++17 && ./a.out
res: 4
i: 1 2 3 4 5 6 7 8 9 10
实验03 和for_each模板相结合,捕获
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5, 6};
int multiplier = 2;
/* 按值捕获 eg1 */
std::for_each(vec.begin(), vec.end(), [multiplier](int x){
std::cout << x * multiplier << " ";
});
std::cout << std::endl;
/* 按值捕获 eg2 use = instead*/
std::for_each(vec.begin(), vec.end(), [=](int x){
std::cout << x * multiplier << " ";
});
std::cout << std::endl;
/* 按引用捕获 */
std::for_each(vec.begin(), vec.end(), [&](int x){
multiplier++;
std::cout << x * multiplier << " ";
});
std::cout << std::endl;
}
编译并运行:
g++ lambda_03.cpp -std=c++17 && ./a.out
2 4 6 8 10 12
2 4 6 8 10 12
3 8 15 24 35 48
总结
- 判断lambda的使用场景
- 关注作用域
- 函数体少
- 捕获时注意是否需要捕获,若捕获是按值捕获还是按引用捕获