《C11function和bind》[作者的个人Gitee](友人A (friend-a188881041351) - Gitee.com)每日一言:“**存在是一场无尽的对话我们既是提问者也是答案。”一、functiontemplate class T class function; // undefined template class Ret, class... Args class functionRet(Args...);std::function是一个类模板也是一个包装器。std::function的实例对象可以包装存储其他的可调用对象包括函数指针、仿函数、lambda、bind表达式等存储的可调用对象被称为std::function的目标。若std::function不含目标则称它为空。调用空std::function的目标将抛出std::bad_function_call异常。以上代码是function原型他被定义在头文件中。官方链接function - C Reference。function返回值,(参数1参数2参数3…)函数指针、仿函数、lambda等可调用对象的类型各不相同std::function的优势就统一类型对它们进行统一的包装这样在很多地方就方便声明可调用对象的类型。代码样例一#include iostream #include functional using namespace std; int f(int a,int b) { return a b; } struct Functor { public: int operator()(int a,int b) { return a b; } }; int main() { //包装各种可调用对象 functionint(int,int) f1 f;//函数指针 functionint(int,int) f2 Functor();//函数对象 functionint(int,int) f3 [](int a,int b){return a b;};//lambda cout f1(1,2) endl; cout f2(1,2) endl; cout f3(1,2) endl; return 0; }输出结果如下代码样例二#include iostream #include functional using namespace std; class Plus { public: Plus(int n 10) :_n(n) {} static int Plusi(int a,int b) { return a b; } double Plusd(int a,int b) { return (a b) * _n; } private: int _n; }; int main() { //包装静态成员函数 functionint(int,int) f4 Plus::Plusi;//静态成员函数需要指明类域最好加上也可以不加 cout f4(1,2) endl; //包装普通成员函数 //普通成员函数还有一个隐藏的this指针参数所以绑定时传对象或者传对象的指针过去都可以 functiondouble(Plus*,double,double) f5 Plus::Plusd;//传指针 Plus pd; cout f5(pd,1.1,2.2) endl; functiondouble(Plus,double,double) f6 Plus::Plusd;//传对象 cout f6(pd,1.1,2.2) endl; functiondouble(Plus,double,double) f7 Plus::Plusd;//传右值引用 cout f7(move(pd),1.1,2.2) endl; cout f7(Plus(),1.1,2.2) endl; return 0; }输出结果如下LeetCode逆波兰表达式求值题目优化题目链接LCR 036. 逆波兰表达式求值 - 力扣LeetCodeclass Solution { public: int evalRPN(vectorstring tokens) { stackint st; for(auto str: tokens) { if(str || str - || str * || str /) { int right st.top(); st.pop(); int left st.top(); st.pop(); switch(str[0]) { case : st.push(left right); break; case -: st.push(left - right); break; case *: st.push(left * right); break; case /: st.push(left / right); break; } } else { st.push(stoi((str))); } } return st.top(); } };我们一般的写法就是这样但是我们学了function之后就可以进行优化了我们使用map映射是string和function的方式实现。这种方式的最大好处就是方便扩展假设还有其他运算我们只需要增加map之中的映射即可。优化后的代码如下class Solution { public: int evalRPN(vectorstring tokens) { stackint st; mapstring,functionint(int,int) opFuncMap { {,[](int a,int b){return a b;}}, {-,[](int a,int b){return a - b;}}, {*,[](int a,int b){return a * b;}}, {/,[](int a,int b){return a / b;}} }; for(auto str: tokens) { if(opFuncMap.count(str)) { int right st.top(); st.pop(); int left st.top(); st.pop(); int ret opFuncMap[str](left,right); st.push(ret); } else { st.push(stoi((str))); } } return st.top(); } };二、bindtemplate class Fn, class... Args bind (Fn fn, Args... args); template class Ret, class Fn, class... Args bind (Fn fn, Args... args);bind是一个函数模板他也是一个可调用对象的包装器可以把它看作一个函数适配器对接受的fn可调用对象进行处理后返回一个可调用对象。bind可以用来调整参数个数和参数顺序。bind也在这个头文件中。调用bind的一般形式auto newVallable bind(callable,arg_list);其中newcallable本身就是一个可调用对象arg_list是一个用逗号分隔的参数列表对应给定的callable的参数。当我们调用newcallable时newcallable会调用callable并传给它arg_list中的参数。arg_list中的参数可能包含形如_n的名字其中n是一个整数表示newcallable的参数他们占据了传递给newcallable的参数的位置。数值n表示生成的可调用对象中参数的位置_1为第一个参数_2为第二个参数_3是第三个参数以此类推。而_1、_2…这些占位符都被放在placeholders的一个命名空间中。代码样例一#include iostream #include functional using namespace std; using namespace placeholders; int Sub(int a,int b) { return (a - b) * 10; } int SubX(int a,int b,int c) { return (a - b - c) * 10; } class Plus { public: Plus(int n 10) :_n(n) {} static int Plusi(int a,int b) { return a b; } double Plusd(int a,int b) { return (a b) * _n; } private: int _n; }; int main() { //bind本质返回的是一个仿函数对象 //调整参数顺序_1代表第一个实参_2代表第二个实参 auto sub1 bind(Sub,_1,_2); cout sub1(10,5) endl; auto sub2 bind(Sub,_2,_1); cout sub2(10,5) endl; //调整参数个数 auto sub3 bind(Sub,10,_1); cout sub3(5) endl; auto sub4 bind(Sub,_1,100); cout sub4(5) endl; //分别绑死第1、2、3个参数 auto sub5 bind(SubX,100,_1,_2); cout sub5(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; //成员函数第一个隐式参数绑死就不需要每次都传this了 //普通情况 functiondouble(Plus,double,double) f8 Plus::Plusd; Plus pd_; cout f8(move(pd_),1.1,2.2) endl; cout f8(Plus(),1.1,2.2) endl; //使用bind进行绑定 functiondouble(double,double) f9 bind(Plus::Plusd,Plus(),_1,_2); cout f9(1.1,2.2) endl; return 0; }输出结果如下;代码样例二#include iostream #include functional using namespace std; using namespace placeholders; int main() { // 计算复利的lambda auto func1 [](double rate, double money, int year)-double { double ret money; for (int i 0; i year; i) { ret ret * rate; } return ret - money; }; // 绑死⼀些参数实现出⽀持不同年华利率不同⾦额和不同年份计算出复利的结算利息 functiondouble(double) func3_1_5 bind(func1, 0.015, _1, 3); functiondouble(double) func5_1_5 bind(func1, 0.015, _1, 5); functiondouble(double) func10_2_5 bind(func1, 0.025, _1, 10); functiondouble(double) func20_3_5 bind(func1, 0.035, _1, 30); cout func3_1_5(1000000) endl; cout func5_1_5(1000000) endl; cout func10_2_5(1000000) endl; cout func20_3_5(1000000) endl; return 0; }输出结果如下bind(func1, 0.025, _1, 10);functiondouble(double) func20_3_5 bind(func1, 0.035, _1, 30);cout func3_1_5(1000000) endl; cout func5_1_5(1000000) endl; cout func10_2_5(1000000) endl; cout func20_3_5(1000000) endl; return 0;}输出结果如下 [外链图片转存中...(img-YFqja8rM-1773052460186)] --- 如有错误恳请指正