1 首先看个仿函数的例子

class X {
public:
void operator()(string str) { // 函数调用运算符,返回类型在operator之前
cout << "Calling functor X with parameter " << str<< endl;
}
operator string () const { return "X"; } //类型转换函数,返回类型在operator之后
}; int main()
{
X foo;
foo("Hi"); // 以参数HI调用仿函数X
}
/*
* 仿函数的好处:
* 1. 智能函数: 比常规函数有更多的功能,比如可以保存状态(参数化的函数)
* 2. 有它自己的类型,不用考虑函数重名问题
* 事实上,类带来的其他好处,封装,继承,多态都可以是仿函数的好处
*/

2 参数化的函数

class X {
public:
X(int i) {}
void operator()(string str) {
cout << "Calling functor X with parameter " << str<< endl;
}
}; int main()
{
X(8)("Hi");
} // 为什么需要参数化函数,用2个参数的函数代替不行么? // 只实现+2的功能,如果我想实现加任何数的功能
void add2(int i) {
cout << i+2 << endl;
} // 用全局变量,显然不好
// 用模板实现,加任何值的功能,但是val需要编译时常数
template<int val>
void addVal(int i) {
cout << val+i << endl;
} // 轮到仿函数登场了
class AddValue {
int val;
public:
AddValue(int j) : val(j) { }
void operator()(int i) {
cout << i+val << endl;
}
}; int main()
{
vector<int> vec = { 2, 3, 4, 5};
//for_each(vec.begin(), vec.end(), add2); // {4, 5, 6, 7}
int x = 2;
//for_each(vec.begin(), vec.end(), addVal<x>); // {4, 5, 6, 7} ,编译不过
for_each(vec.begin(), vec.end(), AddValue(x)); // {4, 5, 6, 7}
}

3 内置的仿函数

// 比较 less greater  greater_equal  less_equal  not_equal_to
// 逻辑 logical_and logical_not logical_or
// 算术 multiplies minus plus divide modulus negate int x = multiplies<int>()(3,4); // x = 3 * 4 if (not_equal_to<int>()(x, 10)) // if (x != 10)
cout << x << endl;

4 参数绑定

set<int> myset = { 2, 3, 4, 5};
vector<int> vec; int x = multiplies<int>()(3,4); // x = 3 * 4 // 将元素值乘以10,保存在vec中:
transform(myset.begin(), myset.end(), // 源
back_inserter(vec), // 目的
bind(multiplies<int>(), placeholders::_1, 10)); // 仿函数
// multiplies<int>()的第1个参数替换为myset中的元素值
// vec: {20, 30, 40, 50} void addVal(int i, int val) {
cout << i+val << endl;
}
for_each(vec.begin(), vec.end(), bind(addVal, placeholders::_1, 2)); // C++ 03: bind1st, bind2nd

5 将常规函数转为仿函数

double Pow(double x, double y) {
return pow(x, y);
} int main()
{
set<int> myset = {3, 1, 25, 7, 12};
deque<int> d;
auto f = function<double (double,double)>(Pow); //C++ 11
transform(myset.begin(), myset.end(), // 源地址
back_inserter(d), // 目的
bind(f, placeholders::_1, 2)); // 仿函数
// d: {1, 9, 49, 144, 625}
}
// C++ 03中使用ptr_fun

6 lambda函数

// 想拷贝5<x<20之间的元素到d
set<int> myset = {3, 1, 25, 7, 12};
deque<int> d; // 定义一个函数
bool needCopy(int x){
return (x>20)||(x<5);
}
// 或者用内置仿函数和bind结合
// 两种方法都不方便 transform(myset.begin(), myset.end(), // source
back_inserter(d), // destination
needCopy
); /*
bind(logical_or<bool>,
bind(greater<int>(), placeholders::_1, 20),
bind(less<int>(), placeholders::_1, 5))
*/ // C++ 11 lambda function:
transform(myset.begin(), myset.end(), // source
back_inserter(d), // destination
[](int x){return (x>20)||(x<5);} //lambda函数
);

7 为什么STL中需要仿函数?

set<int> myset = {3, 1, 25, 7, 12}; // myset: {1, 3, 7, 12, 25}
// 同:
set<int, less<int> > myset = {3, 1, 25, 7, 12}; bool lsb_less(int x, int y) {
return (x%10)<(y%10);
} class Lsb_less {
public:
bool operator()(int x, int y) {
return (x%10)<(y%10);
}
};
int main()
{
set<int, Lsb_less> myset = {3, 1, 25, 7, 12}; // myset: {1,12,3,25,7}
...
}

8 谓词

 /*
* 一种特殊的仿函数:
* 1. 返回一个boolean值
* 2. 不改变数据
*/ class NeedCopy {
bool operator()(int x){
return (x>20)||(x<5);
}
}; transform(myset.begin(), myset.end(), // source
back_inserter(d), // destination
NeedCopy()
); // 谓词用于比较或者条件判断

STL基础--仿函数(函数对象)的更多相关文章

  1. STL 算法中函数对象和谓词

    STL 算法中函数对象和谓词 函数对象和谓词定义 函数对象: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.一个类对象,表现出一个函数的特 ...

  2. 3.2 STL中的函数对象类模板

    *: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...

  3. STL中的函数对象实现负数的定义

    // // main.cpp // STL中的函数对象 // // Created by mac on 2019/5/2. // Copyright © 2019年 mac. All rights r ...

  4. STL算法设计理念 - 函数对象和函数对象当参数和返回值

    函数对象: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.一个类对象,表现出一个函数的特征,就是通过"对象名+(参数列表)&qu ...

  5. STL算法设计理念 - 函数对象和函数对象当參数和返回值

    函数对象: 重载函数调用操作符的类.其对象常称为函数对象(function object),即它们是行为类似函数的对象. 一个类对象,表现出一个函数的特征,就是通过"对象名+(參数列表)&q ...

  6. STL算法中函数对象和谓词

    函数对象和谓词定义 函数对象: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.一个类对象,表现出一个函数的特征,就是通过“对象名+(参数列 ...

  7. C++STL 预定义函数对象和函数适配器

    预定义函数对象和函数适配器 预定义函数对象基本概念:标准模板库STL提前定义了很多预定义函数对象,#include <functional> 必须包含. 1使用预定义函数对象: void ...

  8. Python 入门基础10 --函数基础3 函数对象、名称空间、装饰器

    今日内容 1.函数对象 2.名称空间与作用域 3.函数的嵌套调用与闭包 4.装饰器 一.函数对象 1.1 定义 函数名存放的就是函数地址,所以函数名也就是对象,称之为函数对象 1.2 函数对象的应用 ...

  9. python基础之函数对象,嵌套,名称空间和作用域

    函数对象: 函数是第一类对象的含义是函数可以被当作数据处理 函数可用于: def func(): print(‘func’) 1.引用  f = func  把内存地址赋值给f 2.当作参数传给一个函 ...

随机推荐

  1. python time 时间处理

    a='2018-03-26 17:20:11' >>> print time.strftime("%Y%m%d", a)Traceback (most recen ...

  2. 2017.4.4 TCP/IP三次握手,四次挥手

    之前在电话面试的时候,被问到,所以找到一个超级容易理解的图片,自己保存,也算分享.

  3. WINDOWS系统的正确安装-硬盘格式如何选择

    有一种这样的说法,WIN7改装WIN10必须要重新分区,将硬盘格式化为GPT格式(GUID分区表 ), WIN10改装WIN7必须要重新分区,将硬盘格式化为MBR格式. 这种说法一直困扰着我,于是经过 ...

  4. UVA10294 Arif in Dhaka (First Love Part 2)

    题意 PDF 分析 用n颗宝石串成项链和手镯, 每颗宝石的颜色可以t种颜色中的一种,当A类项链经过旋转得B类项链时,A和B属于一类项链, 而手镯不仅可以旋转还可以翻转,当A类手镯经过翻转得得到B类手镯 ...

  5. day21-22Redis Mahout

    PS: Redis 在博客的 JavaEE PS:大数据实时执行3个特性,Storm,kafka,Redis PS:比如在系统中,1s中有大量的请求涌入的系统中,那么请求就存入数据库就挂了,这就需要到 ...

  6. MySQL之高可用MHA部署

    先说一下大概原理 虚拟机A  ip为10.0.3.92           作为master 虚拟机B  ip为10.0.3.102  作为slave1 虚拟机C  ip为10.0.3.103  作为 ...

  7. linux忘记root密码

    在选择系统界面选中要修改的系统(我的就是默认的第一个),按e建进入修改,在修改界面一直下到文件末尾,在末尾前一行左右,找到UTF-8那一行,在这一行敲一个空格,然后打init=/bin/sh 修改完成 ...

  8. Understanding the managed heap

    Understanding the managed heap   Another common problem faced by many Unity developers is the unexpe ...

  9. ViewBag & ViewData

    ViewBag 和ViewData 是ASP.NET MVC 开发当中大家使用很多的传递数据的方法 VB可以称为VD的一块语法糖, VB是使用C# 4.0动态特征, 使得VD也具有动态特性. 下面就是 ...

  10. Python 不可变对象练习

    Python 不可变对象练习 str 是不可变对象,就是对这个对象进行操作不会改变这个对象的数据. 如下: >>> a = 'abc' >>> a.replace( ...