1.lambda表达式
lambda表达式书写格式:[捕捉列表] (参数列表) mutable -> 返回值类型 { 比较的方法 }
int func()
{
int a, b, c, d, e;
a = b = c = d = e = 1;
// 全部传值捕捉
auto f1 = [=]() {
cout << a << b << c << d << e << endl;
};
f1();
}
注意:lambda仅是声明,在使用的时候需要调用一下 。
1.2 参数列表的选择
参数名称 | 该参数 |
= | 作用域的全部参数 |
&参数名称 | 该参数的引用 |
& | 作用域中的全部参数引用 |
注意:
- 可以复合使用
[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量
[&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量
// 1、生命周期(存储区域)
// 2、作用域(编译器编译,用的地方能否找到)
int f = 1;//全局变量可以被捕捉
int func()
{
int a, b, c, d, e;
a = b = c = d = e = 1;
static int x=9;//静态变量也可以被捕捉
// 全部传值捕捉
auto f1 = [=](){
cout << a << b << c << d << e << endl;
};
f1();
// 混合捕捉
auto f2 = [=, &a](){
a++;
cout << a << b << c << d << e << endl;
};
f2();
return 0;
}
- 不能重复使用
比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复
auto f3 = [&, a]() {
//a++; 不然报错
b++;
c++;
d++;
e++;
f++;
x++;
cout << a << b << c << d << e <<f<<x<< endl;
};
- lambda表达式之间不能互相赋值
void (*PF)();
int main()
{
auto f1 = []{cout << "hello world" << endl; };
auto f2 = []{cout << "hello world" << endl; };
// 允许使用一个lambda表达式拷贝构造一个新的副本
auto f3(f2);
f3();
// 可以将lambda表达式赋值给相同类型的函数指针
PF = f2;
PF();
return 0;
}
1.3lambda的本质
实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象(仿函数)的方式处理的,即定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载了operator()。
2.包装器
2.1function包装器
template<class F, class T>
T useF(F f, T x)
{
static int count = 0;
cout << "count:" << ++count << endl;
cout << "count:" << &count << endl;
return f(x);
}
发现由于F的类型不同,我们写的模板实例化了三次。如果不想出现如此多的实例化,我们需要进行一次封装。
function<返回类型(参数类型)>名称
//将函数名进行封装
std::function<double(double)> func1 = f;
//函数对象
std::function<double(double)> func2 = Functor();
// lamber表达式
std::function func3<double(double)> = [](const int a, const int b) {return a + b; };
静态变量的地址一样,说明是同一个静态变量,即模板只实例化了一次。
实例化的类型就是function<double(double)>
3.bind
是一个函数模板,可以用来修改对象,从而使其”适应“参数列表。
调用bind的一般形式:auto newCallable = bind(callable,arg_list);
举例如下:当我们想要和上面一样对下面的函数进行封装以使模板只实例化一次。
// 使用举例
#include <functional>
int Plus(int a, int b)
{
return a + b;
}
int Div(int a, int b)
{
return a / b;
}
int Mul(int a, int b, double rate)
{
return a * b * rate;
}
class Sub
{
public:
int sub(int a, int b)
{
return a - b;
}
};
这里的问题是:Plus、Div函数有两个参数,可Mul函数和在类里面的sub函数却有三个参数。我们需要借助bind强行使sub适应我们的模板。
using namespace placeholders;
int main()
{
// 调整个数, 绑定死固定参数
function<int(int, int)> funcPlus = Plus;
//function<int(Sub, int, int)> funcSub = &Sub::sub;
function<int(int, int)> funcSub = bind(&Sub::sub, Sub(), _1, _2);
//意思是我的参数只有 _1 _2这两个位置敌营的参数 是可变的
//其他是写死的 于是满足了我的模板 function<int(int,int)>
function<int(int, int)> funcMul = bind(Mul, _1, _2, 1.5);
//意思是第三个参数固定是1.5了
//编译通过
map<string, function<int(int, int)>> opFuncMap =
{
{ "+", Plus},
{ "-", bind(&Sub::sub, Sub(), _1, _2)}
};
return 0;
}