lambda
lambda这个词起源于数学上的λ
,在C++中利用lambda表达式,可以方便的定义和创建匿名函数
。lambda可以看做函数对象的升级版。改进了函数对象以下的缺点:
- 使用在泛型算法中的参数传递的过程中
- 比较性质/自定义操作
- 优先级队列
- 智能指针
lambda表达式语法
[捕获外部变量](形参列表)->返回值{操作代码};
如果lambda不需要返回值,那么返回值可以省略。也就是这样:
[捕获外部变量](形参列表){操作代码};
捕获外部变量的方式:
[]:表示不捕获任何外部变量
[=]:以传值的方式捕获外部的所有变量
[&]:以传引用的方式捕获外部的所有变量
[this]:捕获外部的this指针
[=,&a]:以传值的方式捕获外部的所有变量,但是a变量以传引用的方式捕获
[a,b]:以传值的方式捕获外部变量a和b
[a,&b]:a以传值方式捕获,b以传引用的方式捕获
底层实现原理
无参无返回值的lambda
auto func1 = [](){cout << "hello world!" << endl; };
func1();
对应的类:
template<typename T=void>
class TestLambda01
{
public:
TestLambda01() {}
void operator()()const
{
cout << "hello world!" << endl;
}
};
我们其实并不需要定义这样的一个类,也能完成同样的操作。
参数为整型,返回值也为整型
auto func2 = [](int a, int b)->int {return a + b; };
cout<<func2(20, 30)<<endl;
对应的类:
template<typename T = int>
class TestLambda02
{
public:
TestLambda02() {}
int operator()(int a, int b)const
{
return a+b;
}
};
以引用方式获取参数的lambda
int a = 10;
int b = 20;
auto func3 = [&]() // “a”: 无法在非可变 lambda 中修改通过复制捕获
{
int tmp = a;
a = b;
b = tmp;
};
func3();
对应的类
template<typename T = int>
class TestLambda03
{
public:
TestLambda03(int &a, int &b):ma(a), mb(b) {}
void operator()()const
{
int tmp = ma;
ma = mb;
mb = tmp;
}
private:
int &ma;
int &mb;
};
应用lambda表达式排序和按序插入
vector<int> vec;
for(int i = 0;i<20;++i)
{
vec.push_back(rand()%100 + 1);
}
sort(vec.begin(),vec,end,
[](int a,int b)->boll
{
return a>b;
}
);
for(int val:vec)
{
cout<<val<<" ";
}
cout<<endl;
//65按序插入序列,要找第一个小于65的数字
auto it = find_if(vec.begin(),vec.end(),
[](int a)->bool
{
return a<65;
});
if(it != vec.end())
{
vec.insert(it,65);
}
总结
lambda中的捕获参数列表对应类中成员变量的类型,返回值和参数列表对应operator()的返回值和参数列表。
问题
既然lambda表达式只能使用在语句中,如果想跨语句使用之前定义好的lambda表达式,怎么办呢?用什么类型来表示lambda表达式?
当然是用function类型来表示函数对象的类型了
因为bind1st,bind2nd以及bind绑定器都会产生函数对象,function就是服务于他们的。
应用
labmda表达式代替Switch
map<int, function<int(int, int)>> caculateMap;
caculateMap[1] = [](int a, int b)->int {return a + b; };
caculateMap[2] = [](int a, int b)->int {return a - b; };
caculateMap[3] = [](int a, int b)->int {return a * b; };
caculateMap[4] = [](int a, int b)->int {return a / b; };
cout << "选择:";
int choice;
cin >> choice;
cout << "10 op 15:" << caculateMap[choice](10, 15) << endl;
lambda实现自定义删除器
// 智能指针自定义删除器 delete p; FILE* fclose(FILE*)
unique_ptr<FILE, function<void(FILE*)>>
ptr1(fopen("data.txt", "w"),
[](FILE *pf) {fclose(pf); });
lambda实现多种比较操作
class Data
{
public:
Data(int val1 = 10, int val2 = 10) :ma(val1), mb(val2) {}
//bool operator>(const Data &data)const { return ma > data.ma; }
//bool operator<(const Data &data)const { return ma < data.ma; }
int ma;
int mb;
};
int main()
{
// 优先级队列
//priority_queue<Data> queue;
using FUNC = function<bool(Data&, Data&)>;
priority_queue<Data, vector<Data>, FUNC>
maxHeap([](Data &d1, Data &d2)->bool
{
return d1.mb > d2.mb;
});
maxHeap.push(Data(10, 20));
maxHeap.push(Data(15, 15));
maxHeap.push(Data(20, 10));
}
这样就可以灵活的实现比较了,不论我是比较ma还是mb来确定大小。