• 函数对象:具有函数性质的对象
  • 使得用户像使用函数一样使用它
  • 一般函数提供两个版本,第一个版本使用operator < ;第二版本需要用户 指定某种操作
  • 第二版本就是设计一个函数,将函数指针作为算法的一个参数;或者将函数操作设计成为一个仿函数,就语言层面是一个class,再以该仿函数产生一个对象,并以此对象作为算法的一个参数
  • 函数指针就可以完成任务,为啥需要引入 函数对象呢?因为函数指针无法满足STL对抽象性的要求,也无法适配STL的其余组件(适配器)搭配,产生灵活的变化
  • 仿函数就是行为类似函数的对象,为了实现这个功能点,其类别定义中必须自定义(改写或者重载)function call运算子(operator() ),这样就可以在函数的对象后面加上一对小括号,以此来调用函数所定义的 operator()

 分类

  • 操作个数:一元、二元
  • 功能划分:算法运算、关系运算、逻辑运算

unary_function

  • 用于呈现一元函数的参数型别 和 返回值的型别
//STL规定 每一个Adaptable Unary Function都应该继承这个型别
template <class Arg,class Result>
struct unary_function{typedef Arg argument_type;typedef Result result_type;
};
  • 某一个仿函数继承了 unary_function ,其用户便可以获取这个仿函数的参数型别
//以下函数继承了unary_function
template <class T>
struct negate : public unary_function<T,T>{T operator()(const T& x)const {return -x;}
};//以下配接器(adapter) 用来表示某个仿函数的逻辑
template <class Predicate>
class ungry_negate{
public:bool operator()(const typename Predicate::argument_type& x)const{}
};

binary_function

  • 用于呈现二元函数的第一参数型别、第二参数型别和返回数值型别

//STL规定 每一个Adaptable Binary Function都应该继承这个型别
template <class Arg1,class Arg2,class Result>
struct binary_function{typedef Arg1 first_argument_type;typedef Arg2 second_argument_type;typedef Result result_type;
};//以下函数继承了unary_function
template <class T>
struct plus : public binary_function<T,T,T>{T operator()(const T& x,const T&y)const {return x+y;}
};//以下配接器(adapter) 用来将某个二元函数转化为一元函数
template <class Operation>
class binder1st{
protected:Operation op;typedef typename Operation::first_argument_type value;
public:typename Operation::result_type operator()(const typename Operation::second_argument_type& x)const{}
};

算数类仿函数

  • 加法、减法、乘法、除法、模(余数)、否
  • 除了否是一元函数,其余的都是二元函数
  • 加法  plus<T>
template <class T> struct plus {T operator() (const T& x, const T& y) const {return x+y;}typedef T first_argument_type;typedef T second_argument_type;typedef T result_type;
};
// plus example
#include <iostream>     // std::cout
#include <functional>   // std::plus
#include <algorithm>    // std::transformint main () {int first[]={1,2,3,4,5};int second[]={10,20,30,40,50};int results[5];std::transform (first, first+5, second, results, std::plus<int>());for (int i=0; i<5; i++)std::cout << results[i] << ' ';std::cout << '\n';return 0;
}
  • 减法  minus<T>
template <class T> struct minus {T operator() (const T& x, const T& y) const {return x-y;}typedef T first_argument_type;typedef T second_argument_type;typedef T result_type;
};
// minus example
#include <iostream>     // std::cout
#include <functional>   // std::minus
#include <algorithm>    // std::transformint main () {int numbers[]={10,20,30};int result;result = std::accumulate (numbers, numbers+3, 100, std::minus<int>());std::cout << "The result of 100-10-20-30 is " << result << ".\n";return 0;
}
  • 乘法  multiplies<T>
template <class T> struct multiplies {T operator() (const T& x, const T& y) const {return x*y;}typedef T first_argument_type;typedef T second_argument_type;typedef T result_type;
};
// factorials (multiplies example)
#include <iostream>     // std::cout
#include <functional>   // std::multiplies
#include <numeric>      // std::partial_sumint main () {int numbers[9];int factorials[9];for (int i=0;i<9;i++) numbers[i]=i+1;std::partial_sum (numbers, numbers+9, factorials, std::multiplies<int>());for (int i=0; i<9; i++)std::cout << numbers[i] << "! is " << factorials[i] << '\n';return 0;
}Edit & Run
  • 除法  divides<T>
template <class T> struct divides {T operator() (const T& x, const T& y) const {return x/y;}typedef T first_argument_type;typedef T second_argument_type;typedef T result_type;
};
// divides example
#include <iostream>     // std::cout
#include <functional>   // std::divides
#include <algorithm>    // std::transformint main () {int first[]={10,40,90,40,10};int second[]={1,2,3,4,5};int results[5];std::transform (first, first+5, second, results, std::divides<int>());for (int i=0; i<5; i++)std::cout << results[i] << ' ';std::cout << '\n';return 0;
}
  • 模(余数)  modules<T>
template <class T> struct modulus {T operator() (const T& x, const T& y) const {return x%y;}typedef T first_argument_type;typedef T second_argument_type;typedef T result_type;
};
// modulus example
#include <iostream>     // std::cout
#include <functional>   // std::modulus, std::bind2nd
#include <algorithm>    // std::transformint main () {int numbers[]={1,2,3,4,5};int remainders[5];std::transform (numbers, numbers+5, remainders, std::bind2nd(std::modulus<int>(),2));for (int i=0; i<5; i++)std::cout << numbers[i] << " is " << (remainders[i]==0?"even":"odd") << '\n';return 0;
}
  • 否  negate<T>
template <class T> struct negate {T operator() (const T& x) const {return -x;}typedef T argument_type;typedef T result_type;
};
// negate example
#include <iostream>     // std::cout
#include <functional>   // std::negate
#include <algorithm>    // std::transformint main () {int numbers[]={10,-20,30,-40,50};std::transform (numbers, numbers+5, numbers, std::negate<int>());for (int i=0; i<5; i++)std::cout << numbers[i] << ' ';std::cout << '\n';return 0;
}
  • 可以创建一个指定类型的对象或者产生一个无名的临时对象来履行对应的函数的功能

证同元素

  • 即数值A如果和该元素做op运算,会得到A自己
  • 加法的证同元素为0,因为任何元素加上0仍然是他自己
  • 乘法的证同元素是1 ,因为任何元素乘以1仍然是他自己

关系运算类仿函数

  • 等于 equal_to<T>
template <class T> struct equal_to {bool operator() (const T& x, const T& y) const {return x==y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// equal_to example
#include <iostream>     // std::cout
#include <utility>      // std::pair
#include <functional>   // std::equal_to
#include <algorithm>    // std::mismatchint main () {std::pair<int*,int*> ptiter;int foo[]={10,20,30,40,50};int bar[]={10,20,40,80,160};ptiter = std::mismatch (foo, foo+5, bar, std::equal_to<int>());std::cout << "First mismatching pair is: " << *ptiter.first;std::cout << " and " << *ptiter.second << '\n';return 0;
}
  • 不等于 not_equal_to<T>
template <class T> struct not_equal_to {bool operator() (const T& x, const T& y) const {return x!=y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// not_equal_to example
#include <iostream>     // std::cout
#include <functional>   // std::not_equal_to
#include <algorithm>    // std::adjacent_findint main () {int numbers[]={10,10,10,20,20};int* pt = std::adjacent_find (numbers, numbers+5, std::not_equal_to<int>()) +1;std::cout << "The first different element is " << *pt << '\n';return 0;
}
  • 大于 greater<T>
template <class T> struct greater {bool operator() (const T& x, const T& y) const {return x>y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// greater example
#include <iostream>     // std::cout
#include <functional>   // std::greater
#include <algorithm>    // std::sortint main () {int numbers[]={20,40,50,10,30};std::sort (numbers, numbers+5, std::greater<int>());for (int i=0; i<5; i++)std::cout << numbers[i] << ' ';std::cout << '\n';return 0;
}
  • 大于等于 greater_equal<T>
template <class T> struct greater_equal {bool operator() (const T& x, const T& y) const {return x>=y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// greater_equal example
#include <iostream>     // std::cout
#include <functional>   // std::greater_equal, std::bind2nd
#include <algorithm>    // std::count_ifint main () {int numbers[]={20,-30,10,-40,0};int cx = std::count_if (numbers, numbers+5, std::bind2nd(std::greater_equal<int>(),0));std::cout << "There are " << cx << " non-negative elements.\n";return 0;
}
  • 小于 less<T>
template <class T> struct less {bool operator() (const T& x, const T& y) const {return x<y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// less example
#include <iostream>     // std::cout
#include <functional>   // std::less
#include <algorithm>    // std::sort, std::includesint main () {int foo[]={10,20,5,15,25};int bar[]={15,10,20};std::sort (foo, foo+5, std::less<int>());  // 5 10 15 20 25std::sort (bar, bar+3, std::less<int>());  //   10 15 20if (std::includes (foo, foo+5, bar, bar+3, std::less<int>()))std::cout << "foo includes bar.\n";return 0;
}
  • 小于等于 less_equal<T>
template <class T> struct less_equal {bool operator() (const T& x, const T& y) const {return x<=y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// less_equal example
#include <iostream>     // std::cout
#include <functional>   // std::less_equal, std::bind2nd
#include <algorithm>    // std::count_ifint main () {int numbers[]={25,50,75,100,125};int cx = std::count_if (numbers, numbers+5, std::bind2nd(std::less_equal<int>(),100));std::cout << "There are " << cx << " elements lower than or equal to 100.\n";return 0;
}

逻辑运算类仿函数

  • and or Not
  • and 和 or是二元运算符号 Not是一元符号
  • and  logic_and<T>
template <class T> struct logical_and {bool operator() (const T& x, const T& y) const {return x&&y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// logical_and example
#include <iostream>     // std::cout, std::boolalpha
#include <functional>   // std::logical_and
#include <algorithm>    // std::transformint main () {bool foo[] = {true,false,true,false};bool bar[] = {true,true,false,false};bool result[4];std::transform (foo, foo+4, bar, result, std::logical_and<bool>());std::cout << std::boolalpha << "Logical AND:\n";for (int i=0; i<4; i++)std::cout << foo[i] << " AND " << bar[i] << " = " << result[i] << "\n";return 0;
}
  • or    logic_or<T>
template <class T> struct logical_or {bool operator() (const T& x, const T& y) const {return x||y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// logical_or example
#include <iostream>     // std::cout, std::boolalpha
#include <functional>   // std::logical_or
#include <algorithm>    // std::transformint main () {bool foo[] = {true,false,true,false};bool bar[] = {true,true,false,false};bool result[4];std::transform (foo, foo+4, bar, result, std::logical_or<bool>());std::cout << std::boolalpha << "Logical OR:\n";for (int i=0; i<4; i++)std::cout << foo[i] << " OR " << bar[i] << " = " << result[i] << "\n";return 0;
}
  • not   logical_not<T>
template <class T> struct logical_not {bool operator() (const T& x) const {return !x;}typedef T argument_type;typedef bool result_type;
};// logical_not example
#include <iostream>     // std::cout, std::boolalpha
#include <functional>   // std::logical_not
#include <algorithm>    // std::transformint main () {bool values[] = {true,false};bool result[2];std::transform (values, values+2, result, std::logical_not<bool>());std::cout << std::boolalpha << "Logical NOT:\n";for (int i=0; i<2; i++)std::cout << "NOT " << values[i] << " = " << result[i] << "\n";return 0;
}

证同、选择、投射

  • 这一章节的仿函数只是将参数原封不动的传回
  • 其中某些仿函数对传回的参数有刻意的选择 、或者刻意的忽略

STL源码剖析 第七章 仿函数(函数对象)相关推荐

  1. STL源码剖析学习七:stack和queue

    STL源码剖析学习七:stack和queue stack是一种先进后出的数据结构,只有一个出口. 允许新增.删除.获取最顶端的元素,没有任何办法可以存取其他元素,不允许有遍历行为. 缺省情况下用deq ...

  2. STL源码剖析——P142关于list::sort函数

    在list容器中,由于容器自身组织数据的特殊性,所以list提供了自己的排序函数list::sort, 并且实现得相当巧妙,不过<STL源码剖析>的原文中,我有些许疑问,对于该排序算法,侯 ...

  3. STL源码剖析(第二章 空间配置器)

    1.1 空间配置器 以STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象(所有的数值)都存放在容器之内,而容器一定需要配置空间以置放资料.并且allocator称之为&qu ...

  4. 《STL源码剖析》学习--6章--_rotate算法分析

     最近在看侯捷的<STL源码剖析>,其中有许多不太明白之处,后经分析或查找资料有了些理解,现记录一下. <STL源码剖析>学习--6章--random access ite ...

  5. 《STL源码剖析》学习--6章--power算法分析

    最近在看侯捷的<STL源码剖析>,其中有许多不太明白之处,后经分析或查找资料有了些理解,现记录一下. 6章--power算法分析 书本中的算法如下所示: template <clas ...

  6. C++ STL源码剖析 笔记

    写在前面 记录一下<C++ STL源码剖析>中的要点. 一.STL六大组件 容器(container): 各种数据结构,用于存放数据: class template 类泛型: 如vecto ...

  7. STL(C++标准库,体系结构及其内核分析)(STL源码剖析)(更新完毕)

    文章目录 介绍 Level 0:使用C++标准库 0 STL六大部件 0.1 六大部件之间的关系 0.2 复杂度 0.3 容器是前闭后开(左闭右开)区间 1 容器的结构与分类 1.1 使用容器Arra ...

  8. STL源码剖析 算法开篇

    STL源码剖析 算法章节 算法总览_CHYabc123456hh的博客-CSDN博客 质变算法 质变算法 - 会改变操作对象的数值,比如互换.替换.填写.删除.排列组合.分隔.随机重排.排序等 #in ...

  9. 《STL源码剖析》相关面试题总结

    一.STL简介 STL提供六大组件,彼此可以组合套用: 容器 容器就是各种数据结构,我就不多说,看看下面这张图回忆一下就好了,从实现角度看,STL容器是一种class template. 算法 各种常 ...

最新文章

  1. 转: 浅析Fusion-IO和Intel SSD
  2. Verilog中inout端口的使用方法
  3. kingwell Calendar V1.0 日历时间组件
  4. C++ R“()“ 源码转译
  5. s查找mysql服务_MySQL菜鸟实录(一):MySQL服务安装实战
  6. [Yarn] Yarn local-dirs are bad 导致节点处于不健康状态
  7. 产生斜体的html标签,下列可以产生斜体字的 HTML 标签是_____________
  8. 四、kafka整体架构
  9. 哈尔滨工程大学第十四届程序设计竞赛(同步赛)
  10. 词嵌入生成词向量_使用词嵌入创建诗生成器
  11. 利用express启一个server服务
  12. Centos7设置SSH安全策略–指定IP登陆
  13. 2021年最后一天,学点Selenium玩点新鲜~新的一年,让分布式测试有更多玩法
  14. c语言字符串md5加密解密,.net core使用MD5加密解密字符串
  15. Nio实现高性能聊天系统
  16. VMware 终端安装 VMware Tools 以及 开启共享文件夹
  17. java-php-net-python-校园OTO超市系统ssm-视频计算机毕业设计程序
  18. mac下的免费UML建模工具
  19. 二叉树的递归遍历(树UVa548 紫书p155)
  20. 百汇BCR:通过K线可以判断出外汇市场有哪些形态?

热门文章

  1. php hasmany,浅谈laravel orm 中的一对多关系 hasMany
  2. 【转】VScode tasks.json和launch.json的设置
  3. 计算机出现蓝屏怎么解决,电脑出现蓝屏故障0x00000019怎么办?
  4. CCIE理论-第十五篇-IPV6-重分布+ACL+前缀列表
  5. CCNA-第十二篇-STP+ACL(下)
  6. 【CodeForces - 527C】Glass Carving(线段树或者SBT或者set)
  7. 【HDU - 1026 】Ignatius and the Princess I (bfs + 记录路径)
  8. Coursera自动驾驶课程第15讲:GNSS and INS Sensing for Pose Estimation
  9. Apollo自动驾驶入门课程第⑤讲 — 感知(下)
  10. 量子计算机的体积有多大,量子计算机也能实现摩尔定律