STL源码剖析 第七章 仿函数(函数对象)

  • 函数对象:具有函数性质的对象
  • 使得用户像使用函数一样使用它
  • 一般函数提供两个版本,第一个版本使用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;
}

证同、选择、投射

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/446202.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源合同管理系统_「物联网架构」最适合物联网的开源数据库

物联网产生大量的数据&#xff0c;包括流数据、时间序列数据、RFID数据、传感数据等。要有效地管理这些数据&#xff0c;就需要使用数据库。物联网数据的本质需要一种不同类型的数据库。以下是一些数据库&#xff0c;当与物联网一起使用时&#xff0c;会给出非常好的结果。物联…

java 方法重载

概念 代码 package lesson.l10_oop;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/1 14:31* function 方法重载*/ public class Load {public static void main(String[] args) {Load load new Load();load.mOL(4);load.mOL(4, 5);load.mOL("ff&qu…

STL源码剖析 第八章 配接器

设计模式&#xff1a;将一个类的接口转化为另外一个类的接口 配接器的概观和分类 改变仿函数接口 函数配接器 &#xff1b;queue和stack 通过修饰deque函数接口来实现改变容器接口 容器配接器 &#xff1b; insert、reverse、iostream 等iterators他们的接口可以由ite…

python中random库_python标准库之random模块

Python中的random模块用于生成随机数。 下面具体介绍random模块的功能&#xff1a; 1.random.random() #用于生成一个0到1的 随机浮点数&#xff1a;0< n < 1.0 1 import random 2 a random.random() 3 print (a)2.random.uniform(a,b) #用于生成一个指定范围内的随机符…

java 可变个数形参

概念 案例 package lesson.l10_oop;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/1 14:53* function 可变个数形参*/ public class ChangeableFormalParameter {public static void main(String[] args) {ChangeableFormalParameter parameter new Ch…

C++标准库 第七章 STL迭代器

迭代器 能力&#xff1a;行进和存取的能力Input迭代器 一次一个向前读取元素&#xff0c;按此顺序一个一个返回元素例子&#xff1a;从标准输入装置(键盘) 读取数据&#xff0c;同一个数据不会被读取两次&#xff0c;流水一样&#xff0c;指向的是逻辑位置使用前置式递增运算…

nacos集群的ap cp切换_阿里Nacos-配置-多环境

多环境的配置隔离是配置中心最基础的一个功能之一。不同的环境配置的值不一样&#xff0c;比如数据库的信息&#xff0c;业务的配置等。Spring Boot 多环境配置首先我们来回顾下在Spring Boot中用配置文件的方式怎么进行环境的隔离。默认我们都会创建一个application.propertie…

java 值传递机制

说明 案例1 案例2 案例3 案例4 案例5 案例6 package lesson.l11_oop2;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/2 21:24* function 将对象作为参数传递给方法*/ public class Circle {double radius;public double findArea() {return Math.PI * Ma…

密码学专题 非对称加密算法指令概述 RSA

非对称加密算法也称为公开密钥算法&#xff0c;其解决了对称加密算法密钥需要预分配的难题&#xff0c;使得现代密码学的研究和应用取得了重大发展。非对称加密算法的基本特点如下: 加密密钥和解密密钥不相同;密钥对中的一个密钥可以公开(称为公开密钥);根据公开密钥很难推算出…

python元胞自动机模拟交通_结构专栏 | 解析DEFORM软件中的元胞自动机法

点击上方蓝色字体&#xff0c;关注我们导语金属材料的性能取决于内部的微观组织结构&#xff0c;而好的材料性能和价格是产品最大的优势。随着现代物理冶金、热成形技术、热处理技术和计算机技术的兴起与发展&#xff0c;使预测和控制金属材料热加工过程中的组织演变成为可能。…

java 递归

概念 代码 package lesson.l11_oop2;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/2 21:42* function 递归&#xff1a;求n个数的和、乘积*/ public class Recursion {public static void main(String[] args) {Recursion recursion new Recursion();S…

密码学专题 非对称加密算法指令概述 DH算法指令

DH概述 用于密钥交换的公开算法&#xff0c;广泛应用于各种安全协议SSL协议同样支持DH算法DH算法使用之前需要预先共享两个参数&#xff0c;本原元g和模n&#xff0c;这两个参数影响到算法的安全性&#xff0c;因此需要预先生成并检测其安全性生成这些必要参数和管理这些参数的…

java 封装和隐藏 权限修饰符

概念 问题的引入 封装性的体现 权限修饰符 案例 package lesson.l11_oop2;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/3 15:28* function*/ public class Person {private int age;public void setAge(int age) { /* if (age<0||age>…

密码学专题 非对称加密算法指令概述 DSA算法指令

DSA算法和DSA指令概述 DSA算法是美国国家标准的数字签名算法&#xff0c;只具备数字签名的功能不具备密钥交换的功能生成DSA参数然后生成DSA密钥&#xff0c;DSA参数决定了DSA密钥的长度三个指令首先是dsaparam指令&#xff0c;该指令主要用来生成DSA密钥参数&#xff0c;并提…

每天定时打开某个网页_Python科普帖定时通知

0 复习上一关我们学习了selenium&#xff0c;它有可视模式与静默模式这两种浏览器的设置方法&#xff0c;二者各有优势。然后学习了使用.get(URL)获取数据&#xff0c;以及解析与提取数据的方法。在这个过程中&#xff0c;我们操作对象的转换过程&#xff1a;除了上面的方法&am…

java 构造器

概念 案例1 package lesson.l11_oop2;/*** Illustration** author DengQing* version 1.0* datetime 2022/7/3 15:28* function*/ public class Person {private int age;private String name;public Person() {this.age 18;}public Person(int age, String name) {this.age …

密码学专题 信息摘要和数字签名指令

信息摘要 区别于对称加密和非对称加密&#xff0c;信息摘要算数是一种不可逆的操作&#xff0c;无论输入数据的大小输出的数据长度是固定的信息摘要算数对输入很敏感&#xff0c;即使数据变化很细微&#xff0c;输出的结果会出现很大的差异从不同输入得到相同的输出的概率非常…

dataframe 筛选_Spark.DataFrame与Spark.ML简介

本文是PySpark销量预测系列第一篇&#xff0c;后面会陆续通过实战案例详细介绍PySpark销量预测流程&#xff0c;包含特征工程、特征筛选、超参搜索、预测算法。在零售销量预测领域&#xff0c;销售小票数据动辄上千万条&#xff0c;这个量级在单机版上进行数据分析/挖掘是非常困…

密码学专题 证书和CA指令 证书和CA功能概述

为什么需要证书 实现了公钥和私钥的相互验证&#xff0c;但是任何人都可以生成很多的密钥对&#xff0c;密钥对并没有关联实体身份&#xff0c;因此诞生可数字证书前提是CA是所有用户都信任的用户需要将自己的信息和公钥交给CA进行认证生成一个属于自己并被其与用户认可的数字…