C++11 函数对象的升级版 ==》lambda表达式。
函数对象的用处:- 使用在泛型算法参数传递,比如排序算法中自定义比较方式、
- 有顺序的数据结构,自定义操作,比如优先级队列、
- 智能指针的释放,可以自定义操作。
一般不会单独使用函数对象。使用时候需要定义一个类,很多时候没有必要,因为要用函数对象,然后定义一个类,只使用一次,这个类就一直存在代码处。
lambda表达式语法:[捕获外部变量](参数列表)->返回值{函数体};
简单例子:
struct cmp{
int operator()(int a, int b) {
return a+b;
}
};
cmp()(10,10);
[](int a, int b){return a+b;}(10,10);
//如果lambda表达式返回值类型很简单就可以编译出来,
可以不写->返回值
从上面可以看出来,
lambda表达式中参数列表就是函数对象重载()中参数,
返回值 的返回值,
函数体 的函数体
lambda表达式捕获值:
lambda 表达式中,捕获外部变量 [] 不捕获变量 [&] 以引用的方式捕获所有外部变量 [=] 以值的方式捕获外部所有变量 [this] 捕获当前类中的this 指针,如果已经使用了 & 或者 =, 默认添加此选项 [bar] 按值捕获 bar 变量,同时不捕获其他变量 [&bar] 按引用捕获 bar 变量,同时不捕获其他变量
auto func = [a, b](){
int tmp = a;
a = b;
b = tmp;
};
上面的lambda表达式,转换成函数对象是下面的样子
编译器一般把只读方法,都修饰成const。
struct Test{
Test(int a, int b) : ma(a), mb(b){}
void operator()() const {
int tmp = a;
a = b;
b = tmp;
}
private:
int ma;
int mb;
};
int a = 10;
int b = 9;
func();
Test test(a,b);
test();
显然上面两种方法都有语法错误,无法修改通过值传递的参数。
改变成按引用传递即可。
在上面这段代码中,想修改const,可以在变量前加 mutable 修饰。
在上面有一个问题,如果改成了引用传递,为什么可以改变?函数对象 operator() 不是还是由const 修饰吗?
struct Test{
Test(int a, int b) : ma(a), mb(b){}
void operator()() const {
int tmp = a;
a = b;
b = tmp;
}
private:
int& ma;
int& mb;
};
并不是改变这两个引用变量本身,
引用底层还是指针,
这四个字节的指针并没有改变,
改变的是指针所指向的内容。
lambda的使用
lambda 只能使用在语句中,如果想要跨语句使用之前定义好的的lambda表达式,该如何做?用什么类型来表示lambda表达式?
lambda 表达式==》函数对象。用function类型
用function对象,表示lambda表达式。 例子一: map> caculateMap; caculateMap[0] = [](int a, int b)->int {return a+b;}; caculateMap[1] = [](int a, int b)->int {return a-b;}; ..... 例子二: 在智能指针中,如果打开了一个文件,那么对于这个文件指针的delete操作,需要自定义,fclose(FILE*) unique_ptr ptr(open("data.txt","r"),[](FILE* p)->void{fclose(p);}); 例子三: 优先级队列的自定义排序规则 struct Date{ int ma; int mb; }; priority_queue , function > priQue([](Date& a, Date& b)->bool { return a.ma > b.ma; }



