前言之前在学muduo网络库时 , 看到陈硕以基于对象编程的方式,大量使用boost
库中的bind
和function
机制,如今,这些概念都已引入至C++11 , 包含在头文件<functional>
中 。
本篇文章主要梳理C++绑定器相关的内容以及C++11中引入的function
机制,其中绑定器主要有三种:bind1st
、bind2nd
、bind
(C++11) 。学完本篇内容,将对C++绑定器及function
机制等的底层实现有深刻理解 , 那么我们开始说吧 。
函数对象首先说说函数对象,之所以说函数对象,是因为绑定器、function
都涉及到该部分概念 。函数对象实际上是类调用operator()()
小括号运算符重载,实现像在“调用函数”一样的效果,因此还有个别名叫“仿函数” 。函数对象示例代码如下:
class Print {public:void operator()(string &s) { cout << s << endl; }};int main() {string s = "hello world!";Print print; //定义了一个函数对象printprint(s);return 0;}
上面代码print(s);
语句,看似像函数调用,其实是类对象print
调用其小括号运算符重载print.operator(string &s)
。print
就是一个函数对象,至此对函数对象就有了基本的认识 。
剖析绑定器bind1st、bind2nd了解了函数对象,接下来我们说说绑定器,为什么需要绑定器?在使用STL
时经常会遇到STL
算法中需要传递某元函数对象,比如在写sort
时 , 第三个参数决定了我们的排序规则,用来接收一个“比较器”函数对象,该函数对象是一个二元的匿名函数对象,形如greator<int>()
或者less<int>()
。二元函数对象的意思是,这个函数对象的小括号运算符重载函数接收两个参数,那么几元就表示接收几个参数 。下面是库中自带的greater
和less
模板类的源码实现 , 可以看到是对小括号运算符重载的实现,sort
第三个参数接收该模板类的二元匿名函数对象 。
template<typename _Tp>struct greater : public binary_function<_Tp, _Tp, bool>{_GLIBCXX14_CONSTEXPRbooloperator()(const _Tp& __x, const _Tp& __y) const{ return __x > __y; }};template<typename _Tp>struct less : public binary_function<_Tp, _Tp, bool>{_GLIBCXX14_CONSTEXPRbooloperator()(const _Tp& __x, const _Tp& __y) const{ return __x < __y; }};
再回到刚才的问题,那为什么需绑定器?由于STL接口的限制,有时我们拿到的函数对象和特定STL算法中要接收的函数对象在参数上并不匹配,意思就是需要传递一个一元函数对象,你有一个二元函数对象,那可以通过绑定器提前绑定二元函数对象的其中一个参数,使得最终返回的是一个一元函数对象,那么从二元函数对象到一元函数对象的转换过程 , 就需要绑定器去实现 。
如STL中的泛型算法find_if
,可用来查找可变长数组vector
中符合某个条件的值(这个条件比如是要大于50,要小于30,要等于25等等) 。其第三个参数需要传递一个一元函数对象,假如现在要找到第一个小于70
的数,可将绑定器与二元函数对象结合,转换为一元函数对象后传递给find_if
。
我们知道系统自带的greater<int>()
和less<int>()
模板类对象是二元匿名函数对象 , 所以需要通过绑定器将其转换为一元函数对象,可以通过bind1st
和bind2nd
去绑定,顾名思义,前者对二元函数对象的第一个参数进行绑定 , 后者对二元函数对象的第二个参数进行绑定,两个绑定器均返回一元函数对象 , 用法如下:
sort(vec.begin(), vec.end(), greater<int>()); //从大到小对vector进行排序find_if(vec.begin(), vec.end(), bind1st(greater<int>(), 70));find_if(vec.begin(), vec.end(), bind2nd(less<int>(), 70));
两个绑定器分别提前绑定了一个参数,使得二元函数对象+绑定器转换为一元函数对象:
operator()(const T &val)greater a > b ====> bind1st(greater<int>(), 70) ====> 70 > blessa < b ====> bind2nd(less<int>(),70) ====> a < 70
下面给出bind1st
绑定过程图,二元函数对象绑定了第一个数为70
,变为一元函数对象,传递给find_if
泛型算法,此时find_if
所实现的功能就是:找出有序降序数组中第一个小于70
的数 , 所以
推荐阅读
- .net core Blazor+自定义日志提供器实现实时日志查看器
- 小样本利器4. 正则化+数据增强 Mixup Family代码实现
- 学习ASP.NET Core Blazor编程系列九——服务器端校验
- nginx 客户端返回499的错误码
- 三、Go环境安装
- 100版本dnf如何给武器镶嵌徽章(dnf如何在装备上镶嵌徽章)
- oppoa93参数配置详情_oppoa93参数配置详情处理器
- 崩坏3武器索尔之锤强度如何
- 天玑1100相当于骁龙多少处理器_天玑1100相当于骁龙什么水平
- 我的世界暗物质武器怎么做(我的世界暗物质套怎么合成)