博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
STL算法之回调函数和函数对象的理解及设计
阅读量:6572 次
发布时间:2019-06-24

本文共 2839 字,大约阅读时间需要 9 分钟。

hot3.png

         STL算法之回调函数和函数对象的理解及设计

                                                By qianghaohao

         
引言:在我们使用STL的算法的时候,很多算法提供回调函数为参数和函数对象来作为参数,提供
更加强大的功能。就比如STL中sort算法来说吧,我们可能一般情况下这么使用sort(v.begin(), v.end());
这种情况下是对容器中元素默认升序排序。那么我们怎么实现降序排序呢?有两种方法,要么用库中提
供的函数对象作为参数,要么自己编写个函数或者函数对象来作为参数。那么问题来了,库中提供的
函数对象怎么用呢?是啥意思呢?即使我们传进去了也不知道为啥这样?传个自己写的函数?那自己
该怎么写呢?怎么写才能符合STL要求的接口呢?所有的这一切其实都可以通过调试代码单步来理解的。
我们没必要专门研究《STL源码剖析》之类的高深书籍,照样也可以看到看懂STL源码的实现。调试的
时候单步跟进去便揭开了庐山正面目,其实里面的代码也挺好理解的,只不过都是用模板写的,看起来
不那么舒服,多看几眼就懂了。STL真是GP程序设计思想啊,一切皆模板.。。。
           
接下来通过使用一个STL的一个accumulate算法来解答上面的所有困惑:
     
首先贴一段完整的代码,看看读者能否看懂每一句代码是怎么运行的,如果不懂看后面的解释:
//以下代码来自:http://www.cplusplus.com/// accumulate example#include 
#include
#include
using namespace std;int myfunction (int x, int y) {return x+2*y;}struct myclass { int operator()(int x, int y) {return x+3*y;}} myobject;int main () { int init = 100; int numbers[] = {10,20,30}; cout << "using default accumulate: "; cout << accumulate(numbers,numbers+3,init); cout << endl; cout << "using functional's minus: "; cout << accumulate (numbers, numbers+3, init, minus
() ); cout << endl; cout << "using custom function: "; cout << accumulate (numbers, numbers+3, init, myfunction ); cout << endl; cout << "using custom object: "; cout << accumulate (numbers, numbers+3, init, myobject ); cout << endl; return 0;}
       
在上面代码中accumulate(numbers,numbers+3,init)这句调用就不解释了,最基本的使用,相信只要接触了STL的都懂。
可能让STL初学者迷惑的是后面三次的调用。接下来逐个分析下:
   
一. 解析:accumulate (numbers, numbers+3, init, minus<int>() );
   猛一看,这句代码不好理解。。。于是查询MSDN或者到C++网站查询使用方法,查看半天结果全英文,最终还是不懂。。。
  没看懂该怎么办呢?没错,开始单步调试,跳进这句代码的调用,豁然开朗:
      没错,我们很幸运地看到了accumulate算法的实现,那么这段代码还看不懂么???稍微懂点模板的很容易看懂了,就一个简单的for
语句迭代累加。。。似乎也没那么神奇!现在我们可以看到我们传的那个函数对象参数就是
__binary_op,函数指针的调用方式就不用说
了吧--
__init = __binary_op(__init, *__first);这句代码便是对我们的函数的调用,可见第一个参数使我们传进去的
init,第二个是STL容器
中的元素。那么我们现在关心的是那个函数对象是怎么实现的,对吧?于是继续跳进
__binary_op函数的调用:
     到了这里上面的所有疑惑估计都豁然开朗了吧!!!我们调用的minus<int>()这个函数对象其实实现的功能是返回x - y。
那么
accumulate (numbers, numbers+3, init, minus<int>() )这句代码实现的功能也就迎刃而解了,它实现的功能就是
init = init - Elem; 这个表达式的累加。
Elem这里代表容器的每个元素。那么最终结果就是60了。
     
二. 解析:accumulate (numbers, numbers+3, init, myfunction );
    这句代码和上面的类似,只不过第三个参数是自己定义的一个回调函数,通过自定义来满足自己的功能需求。那么初学者
的疑惑就来了,该怎么自定义这个回调函数呢?其实不难,从上面的调试中我们就看到了accumulate的实现了,它的第
三个参数
__binary_op是一个含有两个参数的回调函数--
__binary_op(__init, *__first);那么我们只要定义一个含有两个参数
的回调函数即可,当然也要有返回值。这段代码中是这么定义的:
int myfunction (int x, int y) {return x+2*y;}
很明显,这个函数是否和要求的,那么我们就这么写了!!!这下会写自己的回调函数了吧,就这么简单。
     
三.解析:accumulate (numbers, numbers+3, init, myobject );
   这句代码也和上面的完全类似,只不过第三个参数是自己定义的函数对象,定义方法和自定义回调函数一样的,参数和
库中的接口一致即可。给初学者稍微解释下函数对象--函数对象就一个类重载了()运算符,然后就可以用对象名+参数
列表来调用这个重载函数了,这不就极其类似一个函数的调用吗?对,就是这样的,所以称这种对象为函数对象。
这个理解是我自己这么理解,仅供参考!
     
结语:
          到此为止,相信大家对STL算法中回调函数和函数对象有所理解了吧,最起码能看懂别人或者示例代码了吧,也最
起码学会了如何定制自己的回调函数或者函数对象来使用STL的算法了吧。

转载于:https://my.oschina.net/bufferoverflow/blog/689273

你可能感兴趣的文章
清除vlan.dat文件
查看>>
Android 面试常问七道题
查看>>
TestNG介绍 - 1
查看>>
当前用户更改运行方式出现错误的解决办法
查看>>
visual studio 11开发Win8模板
查看>>
Linux下VsFTP和ProFTP用户管理高级技巧 之一
查看>>
Xamarin 技术全解析
查看>>
mySQL用户和权限管理v1
查看>>
烂泥:CentOS6.5光盘以及ISO镜像文件的使用
查看>>
awk入门-保护SSHD
查看>>
可视化就是简单化,可视化就是易用化
查看>>
Spring(三)之自动装配、表达式
查看>>
阿里云发布“码上公益”平台 打造更高效透明的“科技公益”
查看>>
Hadoop Yarn事件处理框架源码分析
查看>>
DockOne微信分享(七十七):用Harbor实现容器镜像仓库的管理和运维
查看>>
监理延期 验收工程款制约三方
查看>>
Monostate模式
查看>>
Java线程的阻塞
查看>>
我美丽的家乡——洪雅[转]
查看>>
区块链监管难题争论不休,这里具体谈谈辅助监管的四种技术
查看>>