C++11--lambda表达式--包装器--bind--1119

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值