在使用c++标准库时,往往会写一些东西来声明意图,如果自己不写就会使用默认版本。函数对象/仿函数可以用lambda的形式来写。
C++ 11 introduced lambdas, allowing the definition of inline functionality, which can be used as a parameter or a local object. Lambdas change the way the C++ standard library is used.
A lambda is a definition of functionality that can be defined inside statements and expressions. Thus, you can use a lambda as an inline function. The minimal lambda function has no parameters ans simply does something.
简化写法
//这一段只是一个对象,相当于一个类型
[]{
std::cout << "hello lambda" << std::endl;
}
//这一段只是一个对象
[]{
std::cout << "hello lambda" << std::endl;
}() //加了括号之后就表示直接调用 输出"hello lambda"
//基本不会这么写,因为只能调用一次,不如直接写大括号里的内容
//这一段只是一个对象
auto L = []{
std::cout << "hello lambda" << std::endl;
}
...
L(); //调用L,输出"hello lambda"
完整形式
[…导入器](…参数) m u t a b l e o p t mutable_{opt} mutableopt t h r o w S p e c o p t throwSpec_{opt} throwSpecopt -> r e t T y p e o p t retType_{opt} retTypeopt{…}
-
可选参数:
m u t a b l e o p t mutable_{opt} mutableopt: 导入器中的内容是否可以被改写
t h r o w S p e c o p t throwSpec_{opt} throwSpecopt :这个函数是否可以扔出异常
r e t T y p e o p t retType_{opt} retTypeopt:返回类型
这三个参数可以都不写,但只要有一个存在,就一定要写前面的小括号;如果三个参数都没有,小括号可写可不写。 -
导入器
取用从外部传进来的参数,可传值或传引用。
1)[]中不加特殊符号就是传值
2)如果是[&b]这种形式表示传引用。
3)[=,&y]表示y是传引用,其他参数都是传值(=在此是默认写法)
举例:下图左右两边是基本等效的(mutable没有体现出来),注意四次id的值。由于是传值,所以不再会受到后来id=42的影响。如果没有mutable,就不可以++id了。
下面三种形式的比较:
举例:1和2形式等效
-
举例:用lambda函数写一个set的排序准则。
用lambda的变量类型,我们一般都用auto
表示。当需要用这个类型作为参数时,使用decltype
。在下图中,就可以把这个类型值传到set的带参数的构造函数中去了。
lambda函数比较奇特,没有默认构造函数,也没有赋值操作。 所以,如果写成std::set<Person, decltype(cmp)> coll
就会报错,必须要把coll(cmp)
加上。
所以,对于一个排序准则,写成class会更加直观一些。
-
举例:删除在30到100之间的数字,左边为lambda的写法,右边是functor的写法
左边写成了内联函数的形式,效率可能会快一点,但侯捷老师也指出,效率主要还是要看算法上,这里的提升是很有限的。
编程举例
@力扣973.最接近原点的K个点
lambda表达式有时候会被用在写自定义的排序函数中:
class Solution {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int k) {
sort(points.begin(), points.end(), [](const vector<int>& u, const vector<int>& v) {
return u[0] * u[0] + u[1] * u[1] < v[0] * v[0] + v[1] * v[1];
});
return {
points.begin(), points.begin() + k};
}
};
当然,也可以不用lambda表达式的形式:
static bool cmp(const vector<int>& u, const vector<int>& v){
return u[0]*u[0]+u[1]+u[1] < v[0]*v[0] + v[1]*v[1];
}
其他讨论:
在类中=
捕捉的是this
对象:https://leetcode-cn.com/circle/discuss/fO4fEy/