当前位置: 首页 > wzjs >正文

郑州企业建网站制作wordpress更改ico

郑州企业建网站制作,wordpress更改ico,十堰优化网站排名公司,做兼职工作上哪个网站招聘lambda与包装器lambda语法捕捉列表lambda的应用lambda的原理包装器functionbindlambda语法 lambda 表达式本质是⼀个匿名函数对象,跟普通函数不同的是他可以定义在函数内部。 lambda 表达式语法使⽤层⽽⾔没有类型,所以我们⼀般是⽤auto或者模板参数定义…

lambda与包装器

  • lambda语法
  • 捕捉列表
  • lambda的应用
  • lambda的原理
  • 包装器
    • function
    • bind

lambda语法

lambda 表达式本质是⼀个匿名函数对象,跟普通函数不同的是他可以定义在函数内部。
lambda 表达式语法使⽤层⽽⾔没有类型,所以我们⼀般是⽤auto或者模板参数定义的对象去接收 lambda 对象
lambda表达式的格式: [capture-list] (parameters)-> return type {function boby }

  1. [capture-list] : 捕捉列表,该列表总是出现在 lambda 函数的开始位置,编译器根据[]来判断接下来的代码是否为 lambda 函数,捕捉列表能够捕捉上⽂中的变量供 lambda 函数使用,捕捉列表可以传值和传引⽤捕捉。捕捉列表为空也不能省略。(捕捉列表只能是已经定义的)
  2. (parameters) :参数列表,与普通函数的参数列表功能类似,如果不需要参数传递,则可以连同()⼀起省略
  3. ->return type :返回值类型,⽤追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。⼀般返回值类型明确情况下,也可省略,由编译器对返回类型进⾏推导。
  4. {function boby} :函数体,函数体内的实现跟普通函数完全类似,在该函数体内,除了可以使⽤其参数外,还可以使⽤所有捕获到的变量,函数体为空也不能省略。
auto add1 = [](int x, int y)->int {return x + y; };
cout << add1(1, 2) << endl;
// 1、捕捉为空也不能省略
// 2、参数为空可以省略
// 3、返回值可以省略,可以通过返回对象⾃动推导
// 4、函数题不能省略
auto func1 = []
{cout << "hello bit" << endl;return 0;
};

捕捉列表

  1. lambda 表达式中默认只能⽤ lambda 函数体和参数中的变量,如果想用外层作⽤域中的变量就需要进⾏捕捉
  2. 第⼀种捕捉⽅式是在捕捉列表中显⽰的传值捕捉和传引⽤捕捉,捕捉的多个变量⽤逗号分割。[x,y, &z] 表⽰x和y值捕捉,z引⽤捕捉。
  3. 第⼆种捕捉⽅式是在捕捉列表中隐式捕捉,我们在捕捉列表写⼀个=表⽰隐式值捕捉,在捕捉列表写⼀个&表⽰隐式引⽤捕捉,这样我们 lambda 表达式中⽤了那些变量,编译器就会⾃动捕捉那些变量
  4. 第三种捕捉⽅式是在捕捉列表中混合使⽤隐式捕捉和显⽰捕捉。[=, &x]表⽰其他变量隐式值捕捉,x引⽤捕捉;[&, x, y]表⽰其他变量引⽤捕捉,x和y值捕捉。当使用混合捕捉时,第⼀个元素必须是&或=,并且&混合捕捉时,后⾯的捕捉变量必须是值捕捉,同理=混合捕捉时,后面的捕捉变量必须是引用捕捉。
  5. lambda 表达式如果在函数局部域中,他可以捕捉 lambda 位置之前定义的变量,不能捕捉静态局部变量和全局变量,静态局部变量和全局变量也不需要捕捉, lambda 表达式中可以直接使⽤。这也意味着 lambda 表达式如果定义在全局位置,捕捉列表必须为空。(但是一般都是将lambda定义在局部区域
  6. 默认情况下, lambda 捕捉列表是被const修饰的,也就是说传值捕捉的过来的对象不能修改,mutable加在参数列表的后⾯可以取消其常量性,也就说使⽤该修饰符后,传值捕捉的对象就可以修改了,但是修改还是形参对象,不会影响实参。使⽤该修饰符后,参数列表不可省略(即使参数为空)。
auto func1 = [a, &b]
{// 值捕捉的变量不能修改,引⽤捕捉的变量可以修改//a++;b++;int ret = a + b;return ret;
};
auto func2 = [=]
{int ret = a + b + c;return ret;
};
auto func6 = []
{int ret = x + m;return ret;
};
auto func4 = [&, a, b]
{//a++;//b++;c++;d++;return a + b + c + d;
};
auto func5 = [=, &a, &b]
{a++;b++;/*c++;d++;*/return a + b + c + d;
};
auto func7 = [=]()mutable
{a++;b++;c++;
};

但如果lambda是写在类里面的,那么lambda是不能够捕获私有成员变量的,也是不能直接使用的,如果想使用需要捕获this指针

class A
{
public:void f(){auto add1 = [this](int a,int b){return a + b + _a1 + _a2};}
private:
int _a1 = 1;
int _a2 = 2;
};

lambda的应用

在学习 lambda 表达式之前,可调用对象只有函数指针和仿函数对象,函数指针的类型定义起来比较麻烦,仿函数要定义⼀个类,相对会比较麻烦。使用 lambda 去定义可调用对象,既简单又方便。

sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
return g1._price < g2._price;
});

因为sort会将迭代器区间传给后面的对象,所以需要两个参数。

lambda的原理

  1. lambda 的原理和范围for很像,编译后从汇编指令层的角度看,压根就没有lambda 和范围for这样的东西。范围for底层是迭代器,⽽lambda底层是仿函数对象,也就说我们写了⼀个lambda 以后,编译器会⽣成⼀个对应的仿函数的类。
  2. 仿函数的类名是编译按⼀定规则⽣成的,保证不同的 lambda ⽣成的类名不同,lambda参数/返回类型/函数体就是仿函数operator()的参数/返回类型/函数体, lambda 的捕捉列表本质是⽣成的仿函数类的成员变量,也就是说捕捉列表的变量都是 lambda 类构造函数的实参,当然隐式捕捉,编译器要看使⽤哪些就传那些对象。

包装器

function

在这里插入图片描述std::function 是⼀个类模板,也是⼀个包装器。 std::function 的实例对象可以包装存储其他的可以调⽤对象,包括函数指针、仿函数、 lambda 、 bind 表达式等,存储的可调用对象被称为 std::function 的⽬标。若 std::function 不含⽬标,则称它为空。调⽤空std::function 的⽬标导致抛出 std::bad_function_call 异常

int f(int a, int b)
{return a + b;
}struct Fun
{
public:int operator()(int a,int b){return (a + b) * 10;}
};int main()
{auto lf = [](int a, int b) {return (a + b) * 30; };function<int(int, int)>f1(f);//function<int(int, int)>f2(Fun());编译器会将其解释为函数声明而不是变量定义,这被称为"最令人烦恼的解析"function<int(int, int)>f2 = Fun();function<int(int, int)>f3(lf);vector<function<int(int, int)>>Vf = { f,Fun(),lf };cout << f1(2, 3) << endl;cout << f2(1, 2) << endl;cout << lf(4, 5) << endl;for (auto p : Vf){cout << p(1, 2) << endl;}return 0;
}

函数指针、仿函数、 lambda 等可调⽤对象的类型各不相同, std::function 的优势就是统⼀类型,对他们都可以进⾏包装,这样在很多地⽅就⽅便声明可调⽤对象的类型。
可以把function当做把可调用对象进行统一为一个类型,这样就可以将其储存到容器中。
如果包的是成员函数的话需要注意,由于类的成员函数的第一个参数是默认为this指针,所以function实例化的类型需要有类的对象的地址或者是对象,即使传的是对象,对象会使用.*操作符对this指针进行调用。

class Plus
{public:Plus(int n = 10):_n(n){}static int plusi(int a, int b){return a + b;}double plusd(double a, double b){return (a + b) * _n;}private:int _n;
};
int main()
{// 包装静态成员函数// 成员函数要指定类域并且前⾯加&才能获取地址//静态成员函数是可以不加&function<int(int, int)> f4 = &Plus::plusi;cout << f4(1, 1) << endl;// 包装普通成员函数// 普通成员函数还有⼀个隐含的this指针参数,所以绑定时传对象或者对象的指针过去都可以function<double(Plus*, double, double)> f5 = &Plus::plusd;Plus pd;cout << f5(&pd, 1.1, 1.1) << endl;function<double(Plus, double, double)> f6 = &Plus::plusd;cout << f6(pd, 1.1, 1.1) << endl;cout << f6(pd, 1.1, 1.1) << endl;function<double(Plus&&, double, double)> f7 = &Plus::plusd;cout << f7(move(pd), 1.1, 1.1) << endl;cout << f7(Plus(), 1.1, 1.1) << endl;
}

bind

  1. bind 是⼀个函数模板,它也是⼀个可调⽤对象的包装器,可以把他看做⼀个函数适配器,对接收的fn可调⽤对象进⾏处理后返回⼀个可调⽤对象。 bind 可以⽤来调整参数个数和参数顺序。bind 也在<functional>这个头⽂件中。
  2. 调⽤bind的⼀般形式: auto newCallable = bind(callable,arg_list); 其中newCallable本⾝是⼀个可调⽤对象,arg_list是⼀个逗号分隔的参数列表,对应给定的callable的参数。当我们调⽤newCallable时,newCallable会调用callable,并传给它arg_list中的参数。
  3. arg_list中的参数可能包含形如_n的名字,其中n是⼀个整数,这些参数是占位符,表⽰newCallable的参数,它们占据了传递给newCallable的参数的位置。数值n表⽰⽣成的可调⽤对象中参数的位置:_1为newCallable的第⼀个参数,_2为第⼆个参数,以此类推。_1/_2/_3…这些占位符放到placeholders的⼀个命名空间中。
using placeholders::_1;
using placeholders::_2;
using placeholders::_3;
int Sub(int a, int b)
{return (a - b) * 10;
}
int main()
{auto sub1 = bind(Sub, _1, _2);cout << sub1(10, 5) << endl;// bind 本质返回的⼀个仿函数对象// 调整参数顺序(不常⽤)// _1代表第⼀个实参// _2代表第⼆个实参// ...auto sub2 = bind(Sub, _2, _1);cout << sub2(10, 5) << endl;// 调整参数个数 (常⽤)auto sub3 = bind(Sub, 100, _1);cout << sub3(5) << endl;auto sub4 = bind(Sub, _1, 100);cout << sub4(5) << endl;// 分别绑死第123个参数auto sub5 = bind(SubX, 100, _1, _2);cout << sub5(5, 1) << endl;cout << bind(SubX, 100, _1, _2)(5, 1) << endl;auto sub6 = bind(SubX, _1, 100, _2);cout << sub6(5, 1) << endl;auto sub7 = bind(SubX, _1, _2, 100);cout << sub7(5, 1) << endl;return 0;
}

bind对于我们之前用function来包装成员函数时第一个参数必须传对象的情况做出了改变,可以用bind来绑定第一个参数,这样在后续调用该可调用对象的时候就可以不用传对象了

// 成员函数对象进⾏绑死,就不需要每次都传递了
function<double(Plus&&, double, double)> f6 = &Plus::plusd;
Plus pd;
cout << pd.plusd(1.1, 1.1) << endl;
cout << f6(move(pd), 1.1, 1.1) << endl;
cout << f6(Plus(), 1.1, 1.1) << endl;auto f = bind(&Plus::plusd, &pd, _1, _2);
function<double(double, double)> f2 = bind(&Plus::plusd, &pd, _1, _2);
cout << f(1.1,1.1) << endl;
cout << f2(1.1, 1.1) << endl;
http://www.dtcms.com/wzjs/586744.html

相关文章:

  • 我想自己建个网站 应该怎么做做网站用ui好还是ps
  • 深圳做网站公司用dw做的网站怎么发布
  • 上海营销型网站建设方案如何开发自己的app
  • 自己做团购网站怎么样金牛区建设和交通局网站
  • 购物网站建设平台宁德市是哪个省
  • 安庆网站建设推荐安徽秒搜科技wordpress 破解主题下载地址
  • php做网站都需要学什么cpanel转移网站
  • 苏州网站建设公司书生商友作文素材网
  • 网站访客记录做导航网站用什么源码
  • 医院网站建设医生需要做什么电商平台运营方案思路
  • 网站如何快速被收录鞍山玉佛苑官网
  • 提供微网站制作电话汽车网站
  • 网站出现弹窗好的公众号
  • 网站更新方案国外ui界面设计网站
  • 重生做皇帝小说网站清新区住房和城乡建设部网站
  • 四川省建设建设监理协会网站自己做视频网站收益怎么来
  • 学点啥网站档案网站建设网页
  • 辽阳做网站公司网页制作与设计书籍心得体会
  • 郑州建设高端网站自己设计logo软件
  • 做网站的需要什么软件中国50强企业管理培训机构
  • 河北省建设局网站首页wordpress 4.7.9漏洞
  • 中国备案查询网站网站开发月薪多少钱
  • 备案个人可以做视频网站吗门户网站建设投标书
  • 网站开发技术及软件介绍湖北省两学一做网站
  • 投诉网站怎么做哪些网站可以做店淘客
  • 网站自定义代码游戏网站后台建设
  • 湖南的商城网站建设营销型网站建设公司平台
  • j建设网站网站源码下载音乐
  • 电子商务网站开发书例子济南网站建设分销商城
  • 智能建站价格h5免费制作平台八图