试想有一排序函数sort(intarr〔〕)默认为升序排序,如果想更改为降序排列,最直接的方法就是在函数体中修改比较运算符,但这种修改函数体的方法不够灵活,特别是如果sort(intarr〔〕)要封装到库(接口与实现分离)时,库使用者是无法去修改函数体的。理想的方法是修改接口,在接口在添加一函数指针做为形式参数,在函数体中调用函数指针,这样,函数体中的代码就可以固定下来,而选择升序还是降序排列,则由函数指针指向的函数来决定。 函数指针、函数对象、Lambda表达式都可以实现同样的功能:structFuncObj{constexprFuncObj()intoperator()(inta){returnrun(a);}thisisanoncapturinglambda,theoperatorcanbeinastaticfunctionstaticintrun(inta){}};typedefint(funcp)(inta);templatefuncpfoointfunc(inta)intfunc(inta,funcpfoo){foo(a);}intfunc(inta,FuncObjlt){lt(a);}intfuncpRelated(inta){}intmain(){autolambda〔〕(inta){};类型相同,不能捕捉coutfunc(23,funcpRelated)coutfunc(24,lambda)FuncOcoutfunc(25,obj)functionint(int)fintobjFuncObj();coutfintobj(26)functionFuncObj::run(1);thisisworkingreturn0;} 函数指针、函数对象、Lambda表达式对STL算法的使用:includeiostreamincludevectorincludeincludecmathincludectimeconstlongSize139L;constlongSize2100Size1;constlongSize3100Size2;boolf3(intx){returnx30;}boolf13(intx){returnx130;}intmain(){usingstd::std::vectorintnumbers(Size1);std::srand(std::time(0));std::generate(numbers。begin(),numbers。end(),std::rand);usingfunctionpointerscoutSamplesizeSize1;intcount3std::countif(numbers。begin(),numbers。end(),f3);coutCountofnumberspisibleby3:count3;intcount13std::countif(numbers。begin(),numbers。end(),f13);coutCountofnumberspisibleby13:count13;increasenumberofnumbersnumbers。resize(Size2);std::generate(numbers。begin(),numbers。end(),std::rand);coutSamplesizeSize2;usingafunctorclassfmod{private:public:fmod(intd1):dv(d){}booloperator()(intx){returnxdv0;}};count3std::countif(numbers。begin(),numbers。end(),fmod(3));coutCountofnumberspisibleby3:count3;count13std::countif(numbers。begin(),numbers。end(),fmod(13));coutCountofnumberspisibleby13:count13;increasenumberofnumbersagainnumbers。resize(Size3);std::generate(numbers。begin(),numbers。end(),std::rand);coutSamplesizeSize3;usinglambdascount3std::countif(numbers。begin(),numbers。end(),〔〕(intx){returnx30;});coutCountofnumberspisibleby3:count3;count13std::countif(numbers。begin(),numbers。end(),〔〕(intx){returnx130;});coutCountofnumberspisibleby13:count13;std::cin。get();return0;} 输出:Samplesize39Countofnumberspisibleby3:14Countofnumberspisibleby13:0Samplesize3900Countofnumberspisibleby3:1365Countofnumberspisibleby13:289Samplesize390000Countofnumberspisibleby3:129968Countofnumberspisibleby13:30393 函数数指针、函数对象、Lambda表达式的使用,可以从以下几个方面来区别: 1距离:让定义位于使用的地方最近是一种最佳的选择。这是Lambda表达式的优势。函数对象是次优的选择,因为函数对象的类也可以定义在函数内部。最差的是函数指针了,距离最远。 2简洁:是指代码的简洁度。Lambda表达式的代码最简洁,函数指针次之,函数对象虽然相对于函数指针来说,可以实现状态数据的存储,但代码的简洁度最差。 3效率 这三种方法的相对效率取决于编译器内联那些东西。函数指针方法阻止了内联(能够内联的代码,执行效率比较高),因为编译器传统上不会内联其地址被获取的函数,因为函数地址的概念意味着非内联函数。而函数对象和lambda通常不会阻止内联。 4功能 lambda有一些额外的功能。具体地说,lambad可访问作用域内的任何动态变量;要捕获要使用的变量,可将其名称放在中括号内。如果只指定了变量名,如〔z〕,将按值访问变量;如果在名称前加上,如〔count〕,将按引用访问变量。〔〕让您能够按引用访问所有动态变量,而〔〕让您能够按值访问所有动态变量。还可混合使用这两种方式,例如〔ted,ed〕让您能够按值访问ted以及按引用访问ed,〔,ted〕让您能够按值访问ted以及按引用访问其他所有动态变量,,ed让您能够按引用访问ed以及按值访问其他所有动态变量。 看下面的实例:lambda1。cppusecapturedvariablesincludeiostreamincludevectorincludeincludecmathincludectimeconstlongSize390000L;intmain(){usingstd::std::vectorintnumbers(Size);std::srand(std::time(0));std::generate(numbers。begin(),numbers。end(),std::rand);coutSamplesizeSusinglambdasintcount3std::countif(numbers。begin(),numbers。end(),〔〕(intx){returnx30;});coutCountofnumberspisibleby3:count3;intcount130;std::foreach(numbers。begin(),numbers。end(),〔count13〕(intx){count13x130;});coutCountofnumberspisibleby13:count13;usingasinglelambdacount3count130;std::foreach(numbers。begin(),numbers。end(),〔〕(intx){count3x30;count13x130;});coutCountofnumberspisibleby3:count3;coutCountofnumberspisibleby13:count13;std::cin。get();return0;} 输出:Samplesize390000Countofnumberspisibleby3:130144Countofnumberspisibleby13:29939Countofnumberspisibleby3:130144Countofnumberspisibleby13:29939 用表格综合一下以上4项区别: 表格数据: 函数指针 函数对象 lambda表达式 距离 定位位置与使用位置 最差 次优 最优 简洁 代码的简洁度 次优 最差 最优 效率 可内联的代码效率要高 不能内联 可内联 可内联 功能 额外功能 可访问作用域内的任何动态变量 ref StephenPrata:《CPrimerPlus(6th2011)》 End