STL源码剖析(仿函数/bind2nd)
仿函数(functors)其实就是重载了operator()的对象。
下面简单先看看它的一个例子:
#include <iostream>
using namespace std; template<typename T>
struct m_plus
{
T operator()(const T& x, const T& y) { return x + y; }
}; int main(int argc, char *argv[])
{
// 定义其对象 调用其operator()
m_plus<int> op;
cout << op(, ) << endl;
// 产生一个匿名对象 这是仿函数的主流用法
cout << m_plus<int>()(, ) << endl;
return ;
}
既然仿函数跟函数的用法类同,那为什么不直接使用函数指针代替呢?
个人认为有两个原因
1.仿函数可以有自己的状态,而函数指针则不行(有的使用template或者static变量可以实现)。
我们可以这样子使用仿函数:
#include <iostream>
using namespace std; template<typename T, T add>
struct m_plus
{
m_plus() { _add = add; }
T operator()(const T& x) { return x + _add; }
// 仿函数可以具有自己的状态
int _add;
}; int main(int argc, char *argv[])
{
m_plus<int, > op;
cout << op() << endl;
cout << op() << endl;
return ;
}
2.仿函数可以与函数适配器搭配使用。
举一个例子,例如我们如果要使用count_if算法来计算容器中大于10的元素的个数。
如果我们使用greater<int>作为判别式(二元),而count_if只接受一个一元判别式,这时候我们就需要搭配函数适配器一起使用了。
而函数指针不能直接搭配函数适配器一起使用,具体在分析bind2nd的时候会讲到。
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std; int main(int argc, char *argv[])
{
vector<int> coll{ , , , , , , , };
// 接着下面有bind2nd的具体实现
cout << count_if(coll.begin(), coll.end(), bind2nd(greater<int>(), )) << endl;
return ;
}
bind2nd
bind2nd可以将二元仿函数转化为一元仿函数,这看上去好像很神奇,其实它的实现很简单。
首先,二元仿函数会继承自binary_function,其实只是一些typedef,这些都将用于函数适配器。
template <class Arg1, class Arg2, class Result>
struct binary_function {
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
}; template <class T>
struct greater : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const { return x > y; }
};
bind2nd将二元仿函数跟第二个参数型别作为模板型别,下面是具体实现:
template <class Operation, class T>
inline binder2nd<Operation> bind2nd(const Operation& op, const T& x) {
typedef typename Operation::second_argument_type arg2_type;
// 调用binder2nd
return binder2nd<Operation>(op, arg2_type(x));
} // binder2nd是一个一元仿函数(本身可以搭配函数适配器一起使用)
template <class Operation>
class binder2nd
: public unary_function<typename Operation::first_argument_type,
typename Operation::result_type>
{
protected:
// 传进来的二元仿函数
Operation op;
// 传进来的第二个参数 因为仿函数内部可以typedef 而函数指针则不行
// 因此只能适配仿函数 而不能适配函数指针
typename Operation::second_argument_type value;
public:
// 构造函数
binder2nd(const Operation& x,
const typename Operation::second_argument_type& y)
: op(x), value(y) {} // 直接调用二元仿函数
typename Operation::result_type
operator()(const typename Operation::first_argument_type& x) const {
return op(x, value);
}
};
STL源码剖析(仿函数/bind2nd)的更多相关文章
- STL"源码"剖析-重点知识总结
STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...
- 【转载】STL"源码"剖析-重点知识总结
原文:STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点 ...
- STL"源码"剖析
STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略 ...
- 《STL源码剖析》相关面试题总结
原文链接:http://www.cnblogs.com/raichen/p/5817158.html 一.STL简介 STL提供六大组件,彼此可以组合套用: 容器容器就是各种数据结构,我就不多说,看看 ...
- 《STL源码剖析》读书笔记
转载:https://www.cnblogs.com/xiaoyi115/p/3721922.html 直接逼入正题. Standard Template Library简称STL.STL可分为容器( ...
- STL源码剖析之组件
本篇文章开始,进行STL源码剖析的一些知识点,后续系列笔记全是参照<STL源码剖析>进行学习记录的 STL在现在的大部分项目中,实用性已经没有Boost库好了,毕竟STL中仅仅提供了一些容 ...
- 面试题总结(三)、《STL源码剖析》相关面试题总结
声明:本文主要探讨与STL实现相关的面试题,主要参考侯捷的<STL源码剖析>,每一个知识点讨论力求简洁,便于记忆,但讨论深度有限,如要深入研究可点击参考链接,希望对正在找工作的同学有点帮助 ...
- 通读《STL源码剖析》之后的一点读书笔记
直接逼入正题. Standard Template Library简称STL.STL可分为容器(containers).迭代器(iterators).空间配置器(allocator).配接器(adap ...
- 0《STL源码剖析》简介
STL源码剖析 ----侯捷 STL主要包括六个组件: 1.配置器:负责空间配置和管理. 2.迭代器:扮演容器和算法之前的胶合剂,所谓“泛型指针”. 3.容器:各种数据结构,如vector,list, ...
随机推荐
- 洛谷——P2097 资料分发1
P2097 资料分发1 题目描述 有一些电脑,一部分电脑有双向数据线连接.如果一个电脑得到数据,它可以传送到的电脑都可以得到数据.现在,你有这个数据,问你至少将其输入几台电脑,才能使所有电脑得到数据. ...
- Bomb Enemy -- LeetCode
Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' (the number zero), return ...
- JZYZOJ1376 [coci2011]友好数对 容斥定理 状态压缩
http://172.20.6.3/Problem_Show.asp?id=1376 题意:找给出的数中含有相同数字的数对的对数. mmp数论题竟然卡快读,莫名拉低通过率什么的太过分了. 刚开始想到了 ...
- (原创)Stanford Machine Learning (by Andrew NG) --- (week 7) Support Vector Machines
本栏目内容来源于Andrew NG老师讲解的SVM部分,包括SVM的优化目标.最大判定边界.核函数.SVM使用方法.多分类问题等,Machine learning课程地址为:https://www.c ...
- 洛谷 [AHOI2001]质数和分解
题目描述 Description 任何大于 1 的自然数 n 都可以写成若干个大于等于 2 且小于等于 n 的质数之和表达式(包括只有一个数构成的和表达式的情况),并且可能有不止一种质数和的形式.例 ...
- [转]基于全注解的Spring3.1 mvc、myBatis3.1、Mysql的轻量级项目
摘要 对于现在主流的j2ee企业级开发而言,ssh(struts+hibernate+spring)依然是一个事实的标准.由struts充当的mvc调度控制:hibernate的orm持久化映射:sp ...
- 迁移11g Rac中OCR和VOTEDISK
环境:OEL+oracle rac 11.2.0.3 迁移描述:将ocr和votedisk从+DATE上迁移到+OCR_VOTE上: 操作如下: [root@ora2 ~]$ /u01/app/11. ...
- 推荐几个对象映射(Object-Object Map)的库
在进行一些MIS相关的项目开发中,我们经常会涉及到一些数据对象和视图模型之间的互相转换, public class Customer //mapped from db { ...
- JavaScript入门详解
开始开发工作. 一.Alert Confirm Prompt <html> <head> <script type="text/javascript" ...
- Struct2_定义拦截器并使用注解方式作用在Action的方法中
一.目的:通过在方法上加注解控制哪些方法需要登陆后才能访问 二.方式:利用拦截器判断用户是否登陆 三.实现步骤 定义配置文件struts.xml添加节点 1 2 3 4 5 6 7 8 9 1 ...