谓词算术仿函数
谓词谓词概念概念:返回bool类型的仿函数 称为谓词如果operator()接受一个参数,那么叫做一元谓词如果operator()接受两个参数,那么叫做二元谓词带括号的是匿名类 不带括号的是函数指针(匿名构造函数,不需要将重载括号写后边, 内部逻辑自动补括号)mycompare()等同于mycompare m;一元谓词#include<iostream>#include<vect
谓词
谓词概念
概念:
-
返回bool类型的仿函数 称为谓词
-
如果operator()接受一个参数,那么叫做一元谓词
-
如果operator()接受两个参数,那么叫做二元谓词
-
带括号的是匿名类 不带括号的是函数指针(匿名构造函数,不需要将重载括号写后边, 内部逻辑自动补括号)mycompare()等同于mycompare m;
一元谓词
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class diaoyong
{
public:
bool operator()(int a)
{
return a > 5; //这里控制条件
}
};
void pushback(vector<int>&a)
{
int b;
cout << "输入要插入的数量" << endl;
cin >> b;
for (int i = 0; i < b; i++)
{
int c;
cout << "输入要插入的数据" << endl;
cin >> c;
a.push_back(c);
}
}
void fund(vector<int>&a)
{
vector<int>::iterator it=find_if(a.begin(), a.end(), diaoyong());// diaoyong()匿名的函数对象 或者创建bool上的类的对象 写进去也可以
if (it == a.end()) //带括号的是匿名类 不带括号的是函数指针(匿名构造函数,不需要将重载括号写后边, 内部逻辑自动补括号)
{
cout << "未找到大于5的数字" << endl;
}
else
{
cout << "找到了大于5的数字在"<<*it<< endl;
}
}
int main()
{
vector<int>a;
pushback(a);
fund(a);
system("pause");
return 0;
}
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class diaoyong
{
public:
bool operator()(int a)
{
return a > 5; //这里控制条件
}
};
class mycompare
{
public:
bool operator()(int a,int b) const
{
return a > b;
}
};
void pushback(vector<int>&a)
{
int b;
cout << "输入要插入的数量" << endl;
cin >> b;
for (int i = 0; i < b; i++)
{
int c;
cout << "输入要插入的数据" << endl;
cin >> c;
a.push_back(c);
}
sort(a.begin(), a.end(), mycompare());//必须写在这里写别处 比如打印哪里跑不下来
}
/*void fund(vector<int>& a)
{
vector<int>::iterator it=find_if(a.begin(), a.end(), diaoyong());// diaoyong()匿名的函数对象 或者创建bool上的类的对象 写进去也可以
if (it == a.end()) //带括号的是匿名类 不带括号的是函数指针(匿名构造函数,不需要将重载括号写后边, 内部逻辑自动补括号)
{
cout << "未找到大于5的数字" << endl;
}
else
{
cout << "找到了大于5的数字在"<<*it<< endl;
}
}
*/
void printvector(vector<int> &a)
{
for (vector<int>::iterator it = a.begin(); it != a.end(); it++)
{
cout << *it << endl;
}
}
int main()
{
vector<int>a;
pushback(a);
//fund(a);
printvector(a);
system("pause");
return 0;
}
内建函数对象
内建函数对象意义
概念:
-
STL内建了一些函数对象
分类:
-
算术仿函数
-
关系仿函数
-
逻辑仿函数
用法:
-
这些仿函数所产生的对象,用法和一般函数完全相同
-
使用内建函数对象,需要引入头文件#include<functional>
算术仿函数
功能描述:
-
实现四则运算
-
其中negate是一元运算,其他都是二元运算
仿函数原型
#include<iostream>
#include<functional>
using namespace std;
int main()
{
int a;
int b;
cout << "输入要去相反数的数字" << endl;
cin >> a;
negate<int>d;
cout << d(a) << endl;
cout << "输入要相加的两数" << endl;
int e;
cout<<"输入第一个数"<<endl;
cin >> b;
cout << "输入第二个数" << endl;
cin >> e;
plus<int>c;
cout << "和为" << c(b, e) << endl;
system("pause");
return 0;
}
关系仿函数
功能描述:
-
实现关系对比
仿函数原型
#include<iostream>
//#include<algorithm>algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm
#include<functional>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
/*int a;
int b;
cout << "输入要去相反数的数字" << endl;
cin >> a;
negate<int>d;
cout << d(a) << endl;
cout << "输入要相加的两数" << endl;
int e;
cout<<"输入第一个数"<<endl;
cin >> b;
cout << "输入第二个数" << endl;
cin >> e;
plus<int>c;
cout << "和为" << c(b, e) << endl;
*/
vector<int>a;
int b;
cout << "输入要存入的数据数" << endl;
cin >> b;
for (int i = 0; i < b; i++)
{
int c;
cout << "输入要存入的数据" << endl;
cin >> c;
}
sort(a.begin(), a.end(), greater<int>());
for (vector<int>::iterator it = a.begin(); it != a.end(); it++)
{
cout << *it << endl;
}
system("pause");
return 0;
}
逻辑仿函数
功能描述:
-
实现逻辑运算
函数原型:
#include<iostream>
//#include<algorithm>algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm algorithm
#include<functional>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
/*int a;
int b;
cout << "输入要去相反数的数字" << endl;
cin >> a;
negate<int>d;
cout << d(a) << endl;
cout << "输入要相加的两数" << endl;
int e;
cout<<"输入第一个数"<<endl;
cin >> b;
cout << "输入第二个数" << endl;
cin >> e;
plus<int>c;
cout << "和为" << c(b, e) << endl;
vector<int>a;
int b;
cout << "输入要存入的数据数" << endl;
cin >> b;
for (int i = 0; i < b; i++)
{
int c;
cout << "输入要存入的数据" << endl;
cin >> c;
}
sort(a.begin(), a.end(), greater<int>());
for (vector<int>::iterator it = a.begin(); it != a.end(); it++)
{
cout << *it << endl;
}*/
vector<bool>a;
int b;
cout << "输入要存入的数据数" << endl;
cin >> b;
for (int i = 0; i < b; i++)
{
bool c;
cout << "输入要存入的数据" << endl;
cin >> c;
}
for (vector<bool>::iterator it = a.begin(); it != a.end(); it++)
{
cout << *it << endl;
}
cout << endl;
cout << endl;
vector<bool>s;
s.resize(a.size());
transform(a.begin(),a.end(), s.begin(), logical_not<bool>());//注意顺序不是以往的 开始位置 需要复制位置 是先需要复制位置后插入位置
for (vector<bool>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << endl;
}
system("pause");
return 0;
}
仿函数的定义
-
所谓仿函数(functor)就是使用起来像函数一样的东西。如果对某个class进行operator()重载,它就是一个仿函数类,该函数就是一个仿函数
-
函数指针有缺点,最重要的是它无法持有自己的状态(局部状态),也无法达到组件技术中的可适配性(也就是无法再将来某些修饰徐条件加上,以达到改变其状态)。因此,STL算法的特殊版本所接受的所谓的”条件“或”策略“或”一整组操作“都是以仿函数呈现的
-
函数对象是比函数更加通用的概念,因为函数对象可以定义跨越多次调用的可持久的部分(类似静态局部变量),同时又能从对象的外面进行初始化和检查(和静态局部变量不同)
-
一个拥有应用操作符的函数对象可以被完美地内联化(inline),因为它没有涉及到任何指针,后者可能导致拒绝优化。与之形成对比的是,现有的优化器几乎不能(或者完全不能?)将一个通过函数指针的调用内联化。
在标准库中,函数对象被广泛的使用以获得弹性
//仿函数类
template<class T>
struct Greater
{
//仿函数
bool operator()(const T& a, const T& b)
{
return a > b;
}
};
void test()
{
Greater<int> g;
//原型
bool ret = g.operator()(13, 14);
cout << ret << endl;
//简写形式-使用方法和函数类似
ret = g(13, 14);
cout << ret << endl;
}
1、函数对象——重载了()操作符的类
class SumAdd
{
public:
void operator() () //这里两个括号看起来很怪,第一个是表示重载()操作符,第二个表示使用时()中写几个参数和参数的类型,这里没有写参数
{
}
};
2 、一元函数对象和二元函数对象
一元函数对象表示一个参数的函数对象(在类中重载()操作符时规定了一个参数),同理,二元函数对象就是两个参数的函数对象
//一元函数对象
class SumAdd
{
public:
void operator() (int a)
{
...
}
};
//二元函数对象
class SumAdd
{
public:
void operator() (int a,int b)
{
...
}
};
那么有没有三元函数对象呢,按照这个规定,只要重载函数操作符时规定三个参数即可
3、函数对象的使用方法
当了解到函数对象怎么用市其实也很简单,定义一个重载了()的类的对象,然后直接使用()就行,就像用其他操作符一样(比如+ -等等) 具体例子
class myadd
{
public:
int operator() (int &add1 , int &add2 ,int &add3)
{
return add1 + add2 + add3;
}
};
int main(void)
{
myadd myadd; //用类定义一个对象
int a = 6;
int b = 8;
int c = 8;
int temp = myadd(a, b ,c); //直接用()即可
cout << "add:"<<temp << endl;
cout << endl;
system("pause")
}
4、伪函数
由上面例子可见,在重载了()操作符的对象使用()是,很像是在调用一个函数,所以函数对象也叫做伪函数,自己理解这个伪没有什么特殊的含义,就是指调用的样子和调用函数很像而已
5 、涉及函数对象的几个STL 算法
1、for_each()
class mycount
{
public:
void operator()(int &count1)
{
n++;
cout <<"void operator()(int &count1) n:"<< n << endl;
}
void printf_count()
{
cout << n << endl;
}
public:
int n;
};
int main(void)
{
vector<int> v1;
v1.push_back(1);
v1.push_back(3);
v1.push_back(5);mycount mycount;
for_each(v1.begin(), v1.end(), mycount); //匿名函数对象 匿名仿函数
cout << "mycount.n:"<<mycount.n << endl;//输出0
cout << "printf_count:";
mycount.printf_count();//输出0
mycount = for_each(v1.begin(), v1.end(), mycount); //匿名函数对象 匿名仿函数
cout << "2mycount.n:" << mycount.n << endl;//输出3
cout << "2printf_count:";
mycount.printf_count();//输出3
//for_each算法的 函数对象的传递 是元素值传递 ,不是引用传递
/*
template<class _InIt,
class _Fn1> inline
_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
{ // perform function for each element
_DEBUG_RANGE(_First, _Last);
_DEBUG_POINTER(_Func);
return (_For_each(_Unchecked(_First), _Unchecked(_Last), _Func));
}
*/
//分清楚 stl算法返回的值是迭代器 还是 谓词(函数对象)
cout << endl;
system("pause");
因为for_each()中函数对象的传递是值传递而不是引用传递,所以在传递的时候会为形参创建副本,所以改变的知识副本而已,要是想改变实参,就要知道函数返回的是什么,像for_each()返回的是一个对象,所以我们只要用原对象去接就行了 2、find_if()
class IsDiv
{
public:
IsDiv(const int &divisor)
{
this->divisor = divisor;
}
bool operator()(int &t)
{
return (t%divisor == 0);
}
private:
int divisor;
};
int main(void)
{
vector<int> v2;
for (int i = 10; i<33; i++)
{
v2.push_back(i);
}
int a = 4;
IsDiv myDiv(a);
vector<int>::iterator it;
it = find_if(v2.begin(), v2.end(), IsDiv(a));
if (it == v2.end())
{
cout << "容器中没有被4整除的元素" << endl;
}
else
{
cout << "第一个是被4整除的元素是:" << *it << endl;
}
}
ind_if()函数返回的则是一个迭代器,所以才说; !!!分清楚 stl算法返回的值是迭代器 还是 谓词(函数对象)
更多推荐
所有评论(0)