今天来到我们STL系列的第九期:仿函数的讲解
文章图片
文章目录 什么是仿函数?
仿函数的特点:
STL仿函数的分类:
谓词:
内建的仿函数:
算数仿函数:
关系仿函数:
逻辑仿函数:(不常用)
什么是仿函数? 仿函数作为STL六大组件中的其中一个,也称为函数对象,仿函数是一个能行使函数功能的类,仿函数的语法几乎和普通函数调用一样,不过作为仿函数的类,都必须重载 operator() 运算符。
仿函数的主要功能是为了搭配STL算法使用,单独使用仿函数的情况比较少。
仿函数的特点:
- 仿函数在使用时,可以像普通函数那样调用,可以有返回值
- 仿函数超出普通函数的概念,可以有自己的状态
- 函数对象可以作为参数传递
仿函数在使用时,可以像普通函数那样调用,可以有返回值class Mytest {
public:
int operator()(int v1, int v2)
{
return v1 + v2;
}
};
int main()
{
Mytest test01;
cout << test01(1, 2) << endl;
//输出3
return 0;
}
仿函数超出普通函数的概念,可以有自己的状态
class Mytest {
public: void operator()(string std)
{
cout << std << endl;
this->count++;
}
int count=0;
//记录函数调用多少次,内部自己状态
//正常需要定义静态或者全局变量
};
void test02()
{
Mytest test02;
test02("okokok");
test02("okokok");
test02("okokok");
test02("okokok");
cout << test02.count << endl;
//打印4次okokok
}
int main()
{
test02();
return 0;
}
函数对象可以作为参数传递
class Mytest {
public: void operator()(string std)
{
cout << std << endl;
}
};
void doPrint(Mytest &t,string std)
{
t(std);
}
int main()
{
Mytest t;
doPrint(t, "okfun");
//输出okfun
return 0;
}
STL仿函数的分类: 以操作数(operand)的个数划分,分为一元和二元仿函数;
以功能划分,可分为算数运算(Arithmetic)、关系运算(Rational)和逻辑运算(Logical);
谓词:
- 返回bool类型的仿函数称为谓词
- 如果operator()接受一个参数就称为一元谓词
- 如果operator()接受两个参数就称为二元谓词
一元谓词:利用find_if找到大于5的数字
class Mytest {
public: bool operator()(int val)
{
return val > 5;
}
};
int main()
{
vector v{1,2,3,4,5,6,7,8,9 };
auto it = find_if(v.begin(), v.end(), Mytest());
if (it == v.end())
{
cout << "没找到" << endl;
}
else
{
cout << "找到了:" << *it << endl;
}
return 0;
}
二元谓词:sort排序,同前几期介绍的自定义规则排序
class Mytest {
public: bool operator()(int val,int val2)
{
return val>val2;
//从大到小排序
}
};
template
void Show(vector &v)
{
for (auto it = v.begin();
it != v.end();
it++)
{
cout << *it << endl;
}
}
int main()
{
vector v{1,2,3,4,5,6,7,8,9 };
sort(v.begin(), v.end(), Mytest());
Show(v);
return 0;
}
内建的仿函数: STL内部提供了一些仿函数,重载了许多(),便于与STL许多算法搭配使用,使用时我们需要引入头文件#include
算数仿函数:
template |
加法仿函数 |
template |
减法仿函数 |
template |
乘法仿函数 |
template |
除法仿函数 |
template |
取模仿函数 |
template |
取反仿函数 |
void test01()
{
negaten;
cout << n(50.25) << endl;
;
}
void test02()
{
multipliesn;
//对于二元运算只允许两个数据类型相同,所以只能写一种
cout << n(1.1, 2.5);
}
int main()
{
test01();
//输出-50.25
test02();
//输出1.1*2.5
return 0;
}
关系仿函数:
template |
等于 |
template |
不等于 |
template |
大于 |
template |
大于等于 |
template |
小于 |
template |
小于等于 |
我们以大于来举例:
template
void Show(vector &v)
{
for (auto it = v.begin();
it != v.end();
it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
vectorv{ 1,2,3,4,5,6,7,8,9,10 };
Show(v);
// sort(v.begin(), v.end(), greater());
//从大到小
Show(v);
//等同于上面二元谓词的栗子
return 0;
}
【C++|大话STL第九期——仿函数(函数对象)】主要实现对比的关系,最常用的为大于,因为默认的排序为小于,我们使用大于关系仿函数可以简单实现上面从大到小的自定义排序,观察sort源码也能发现:
查看sort的声明,STL声明了两种模板template //需要传入一个_Pr _Pred 自定义的规则
_CONSTEXPR20 void sort(const _RanIt _First, const _RanIt _Last, _Pr _Pred) { // order [_First, _Last)
_Adl_verify_range(_First, _Last);
const auto _UFirst = _Get_unwrapped(_First);
const auto _ULast= _Get_unwrapped(_Last);
_Sort_unchecked(_UFirst, _ULast, _ULast - _UFirst, _Pass_fn(_Pred));
}template //默认的排序 里面传入的是less<>{} 默认小于
_CONSTEXPR20 void sort(const _RanIt _First, const _RanIt _Last) { // order [_First, _Last)
_STD sort(_First, _Last, less<>{});
}
逻辑仿函数:(不常用)
template |
逻辑与 |
template |
逻辑或 |
template |
逻辑非 |
template
void Show(vector &v)
{
for (auto it = v.begin();
it != v.end();
it++)
{
cout << *it << " ";
}
cout << endl;
}int main()
{
vectorv{ false,true,true,false };
Show(v);
//0 1 1 0 vector v2;
v2要提前开辟大小,不然没有空间存放数据
v2.resize(v.size());
//搬运算法----transform
transform(v.begin(), v.end(), v2.begin(),logical_not());
Show(v2);
//1 0 0 1
return 0;
}
对于搬运算法transform,我们查看其源码声明
template
_CONSTEXPR20 _OutIt transform(const _InIt _First, const _InIt _Last, _OutIt _Dest, _Fn _Func)
FIRST对应源容器开始迭代器
LAST 对应源容器结束迭代器
DEST 对应目标容器开始迭代器
Func 对应函数或者函数对象
关于STL中的仿函数我们就到这里了,STL系列也马上结束了,下一期的算法和仿函数经常搭配使用,因此都要好好掌握,有兴趣的可以收藏整个系列,感谢观看!
推荐阅读
- LeetCode刷题|recording:59.螺旋矩阵II
- SLAM|<<Slam十四讲>> ch13环境安装
- 向前端进军|【JavaScript-进阶】详解数据类型,内存分配,API元素对象获取
- 向前端进军|【JavaScript-数组全家福】
- 向前端进军|【JavaScript-函数】函数是什么(一文搞懂js当中的函数,)
- mybatis|搭建MyBatis逆向工程
- 向前端进军|【JavaScript-循环-js循环你学懂了吗】
- JavaScript|【JavaScript 进阶教程】对象新增方法 defineProperty 与 keys 的说明与使用
- #|TSA优化算法——模仿航海过程中外套的喷气推进和蜂群行为(Matlab代码实现)