目录
1.lambda引入
2.语法
3.捕捉列表详解
[ ] 不捕获任何外部变量
[=] 捕获父作用域的所有变量的值,只读不可以修改
[&]捕获父作用域的所有变量的引用,可修改捕获的变量
[val] 只捕获指定的变量值,不可以修改
[&val] 只捕获外部变量val的引用
[this] 捕获当前类的this指针
[=,&]混合
4.mutable
1.lambda引入
在C++98中如想对数据集合中的数据进行排序,需要使用sort函数,该函数默认升序
#include <functional>
#include <algorithm>
int main()
{
int arr[] = { 1,2,6,7,4,3,8 };
sort(arr, arr + sizeof(arr) / sizeof(arr[0]));
for (auto& e : arr)
cout << e;
cout<<endl;
sort(arr, arr + sizeof(arr) / sizeof(arr[0]),greater<int>());
for (auto& e : arr)
cout << e;
return 0;
}
但如果数据对象是自定义类型就需要用户自己写比较函数
#include <vector>
#include <string>
#include <algorithm>
class fruit
{
public:
fruit(string name,int price,int num) :_name(name),_price(price),_num(num){}
int _price;
int _num;
string _name;
};
struct ComparePriceLess
{
bool operator()(const fruit& f1, const fruit& f2)
{
return f1._price < f2._price;
}
};
struct ComparePriceGreater
{
bool operator()(const fruit& f1, const fruit& f2)
{
return f1._price > f2._price;
}
};
int main()
{
vector<fruit> v = { { "苹果", 2, 5 }, { "香蕉", 3, 4 }, { "橙子", 2,3 }, { "菠萝", 1, 4 } };
sort(v.begin(), v.end(), ComparePriceLess());
for (auto& e : v)
cout<<e._name;
return 0;
}
2.语法
但是显然这样的方式每次都要今次那个不同功能的实现,自己手写实在不方便
引入lambda表达式:本质是一个含有operator()的匿名接口(或者类)
lambda的语法:
[capture list] (params list) mutable -> return type { function body }
capture list:捕捉列表,捕获的外部变量列表,可以为空,[ ]开头告诉编译器,现在要用lambda函数
params list:参数列表,与普通函数的形参列表是一样的,如果不需要传递参数,可以连()一起省略
mutable:lambda函数总是一个const函数,但是使用mutable可以取消其常性,使用它的时候,参数列表不能为空,即使参数为空
return type:返回值类型,用追踪返回类型形式声明函数的返回值类型,没有返回值的时候这部分可以省略,返回值类型明确的情况下也可以省略,由编译器对返回值类型推导
function body:函数体,在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。
在lambda中参数列表和返回值类型可以省略,但是捕捉列表和函数体是不能省略的,最简单的lambda函数是[ ]{ },该函数不能做任何事情
那么上面的比较函数可以用lambda函数表示成
#include <vector>
#include <string>
#include <algorithm>
class fruit
{
public:
fruit(string name,int price,int num) :_name(name),_price(price),_num(num){}
int _price;
int _num;
string _name;
};
struct ComparePriceLess
{
bool operator()(const fruit& f1, const fruit& f2)
{
return f1._price < f2._price;
}
};
struct ComparePriceGreater
{
bool operator()(const fruit& f1, const fruit& f2)
{
return f1._price > f2._price;
}
};
int main()
{
vector<fruit> v = { { "苹果", 2, 5 }, { "香蕉", 3, 4 }, { "橙子", 2,3 }, { "菠萝", 1, 4 } };
sort(v.begin(), v.end(), ComparePriceLess());
for (auto& e : v)
cout << e._name;
cout << endl;
sort(v.begin(), v.end(), [](const fruit& f1, const fruit& f2)
{
return f1._price < f2._price;
});
for (auto& e : v)
cout<<e._name;
return 0;
}
3.捕捉列表详解
下面所说的父作用域是指包含lambda函数的语句块
在块作用域以外的lambda函数捕捉列表必须为空
在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都会导致编译报错
[ ] 不捕获任何外部变量
int main()
{
int i = 1;
auto func=[](int i) { cout << i << endl; };
func(i);
return 0;
}
[=] 捕获父作用域的所有变量的值,只读不可以修改
int main()
{
int i = 1;
auto func=[=]() { cout << i << endl; }; //没有形参 而是直接捕捉i
func();
return 0;
}
[&]捕获父作用域的所有变量的引用,可修改捕获的变量
int main()
{
int i = 1;
auto func=[&]() { cout << ++i << endl; };
func();
return 0;
}
[val] 只捕获指定的变量值,不可以修改
int main()
{
int i = 1,j = 2;
auto func=[j]() { cout << i << endl; };
func();
return 0;
}
报错是因为只捕获了j但是没有捕获i
[&val] 只捕获外部变量val的引用
[this] 捕获当前类的this指针
class fruit
{
public:
fruit(int price) :_price(price) {}
void Getprice()
{
cout << _price << endl;
}
void lambda()
{
auto func = [this]() {
this->Getprice();
};
func();
}
private:
int _price;
};
int main()
{
fruit f(1);
f.lambda();
}
[=,&]混合
一定要用,隔开,不允许重复捕捉比如[=,a] 这样会导致编译错误
int main()
{
int i = 1,j = 2;
auto func=[=,&j]() { cout << i <<" "<<++j << endl; };
func();
return 0;
}
综上可以看出lambda相当于一个无名函数,不能直接调用,但是可以用auto推演出类型然后赋给一个函数变量,调用该变量
此外lambda表达式之间不能相互赋值,即使看起来类型是相同的
4.mutable
mutable关键字说明函数体中可以修改值捕捉的变量,但是不影响外部该变量的值,因为值传递是以拷贝方式实现的
int main()
{
int i = 1,j = 2;
auto func=[=,&j]()mutable { cout << ++i <<" "<<++j << endl; };
func();
cout << i << endl;
return 0;
}