在 C++ 中,函数对象(Function Object)也叫仿函数(Functor),是一个类,这个类重载了
()
运算符。从概念上讲,它的行为类似于一个函数,可以像调用函数一样来调用这个类的对象。
例如,下面是一个简单的函数对象类:
class Add {
public:
int operator()(int a, int b) {
return a + b;
}
};int main()
{
//函数对象(仿函数)
Add add;
return 0;
}
这个
Add
类就是一个函数对象。它重载了()
运算符,使得该类的对象可以像函数一样被调用。
作用:为算法提供策略
谓词
返回值为bool类型的普通函数或仿函数都叫谓词
有一个参数叫一元谓词有两个参数叫二元谓词
#include <iostream>
using namespace std;
//谓词
bool method01()
{ }
//谓词
class MyClass{
public:
bool operator()()
{ }
};
//一元谓词
bool method02(int x)
{
}
//二元谓词
bool method03(int x,int y)
{
}
int main()
{
return 0;
}
小括号调用问题
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass()
{
cout<<"无参构造"<<endl;
}
MyClass(int x)
{
cout<<"有参构造"<<endl;
}
bool operator()()
{
cout<<"自定义谓词"<<endl;
return true;
}
};
int main()
{
//函数对象(仿函数)
//MyClass c(); //创建对象后有()不知道调用什么
//MyClass c; //此时调用无参构造
//MyClass c(10); //此时调用有参构造
//MyClass * c = new MyClass; //此时调用无参构造
MyClass * c = new MyClass(10); //此时调用有参构造
bool b = (*c)() //用已经创建的对象后有()是调用重载的()运算符
return 0;}
内建函数对象
C++提供的函数对象
算法类函数对象
template<class T> T plus<T>//加法仿函数
template<class T> T minus<T>//减法仿函数
template<class T> T multiplies<T>//乘法仿函数
template<class T> T divides<T>//除法仿函数
template<class T> T modulus<T>//取模(取余)仿函数
template<class T> T negate<T>//取反仿函数
注意:6个算数类函数对象,除了negate是一元运算,其他都是二元运算
#include<iostream>
using namespace std;
int main()
{
//template<class T> T plus<T>//加法仿函数
plus<int> pl;
int x = pl(10,21);
cout<<x<<endl;
//template<class T> T minus<T>//减法仿函数
minus<int> min;
int y = min(10,21);
cout<<y<<endl;
//....
//template<class T> T negate<T>//取反仿函数,不能对bool取反
negate<int> neg;
int z = neg(-10);
cout<<z<<endl;
return 0;}
关系运算类函数对象
template<class T>bool equal_to<T> //等于
template<class T>bool not_equal_to<T> //不等于
template<class T>bool greater<T> //大于
template<class T>bool greater_equal<T> //大于等于
template<class T>bool less<T> //小于
template<class T>bool less_equal<T> //小于等于
#include <iostream>
#include <string>
#include <stdlib.h>
#incldue <string.h>
using namespace std;
int main()
{
// template<class T>bool equal_to<T>//等于
equal_to<int> eq;
bool b1 = eq(1,1);
cout<<b1<<endl;
char* str01 = (char*) calloc(6,1);
strcpy(str01,"hello");
char* str02 = (char*)calloc(6,1);
strcpy(str02,"hello");
string s01 = sstr01;
string s02 = str02;
equal_to<string> eq;
bool b3 = eq(s01,s02);
cout<<b3<<endl;
return 0;
}
逻辑运算类运算函数
template<class T>bool logical_and<T> //逻辑与
template<class T>bool logical_or<T>//逻辑或
template<class T>bool logical_not<T>//逻辑非
注意:这三个逻辑运算类运算函数,not为一元谓词,其余为二元谓词
#include<iostream>
using namespace std;
int main()
{
//template<class T>bool logical_and<T> //逻辑与
logical_and<bool> a;
bool b1 = a(true,true);
cout<<b1<<endl;
return 0;}
适配器
在 C++ 中,适配器(Adapter)是一种设计模式的实现,它将一个类的接口转换成另一个接口,以满足用户的需求。适配器就像是一个转换器,使得原本不兼容的接口能够协同工作。
从广义上来说,C++ 中有函数适配器、容器适配器等不同类型。
函数对象适配器
以对象作为适配器
使用:bind2nd将绑定的数据放置第二个参数位置
bind1st将绑定的数据放置在第一个参数位置
步骤:
1,创建一个类
2,使该类继承于binary_function
3,泛型萃取
第一泛型为重载的()运算符中第一个形参的数据类型
第二泛型为重载的()运算符中第二个形参的数据类型
第三泛型为重载的()运算符中返回值的数据类型
4,在该类中重载()运算符,尾部加const
5,创建该类对象
6,使用算法,在算法适配器中使用bind1st或bind2nd绑定该对象与传入的值
//1,2,3
class Adapter:public binary_function<int,int,void>
{
//4
public:
void operator()(int x,int y)const
{
}
};
//5
Adapter a;
for_each(v.bedin(),v.end(),bind1st(a,10));
函数指针适配器
以全局函数作为适配器
使用:bind2nd将绑定的数据放置在第二个参数位置
bind1st将绑定的数据放置在第一个参数位置
ptr_fun(函数名)步骤:
1,定义一个全局变量,该函数两个参数
2,使用算法,在算法适配器中使用bind1st或bind2nd绑定该函数与传入的值
#include<iostream>
#include<set>
#include<algorithm>
void my_method(int x,int y)
{
cout<<x<<endl;
cout<<y<<end;
}
int main()
{
set<int> 5;
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(4);
for_each(s.begin(),s.end(),bind2nd(ptr_fun(my_method),100)};
return 0;
成员函数适配器
以成员函数作为适配器
使用:bind2nd将绑定的数据放置到第二个参数位置
bind1st将绑定的数据放置到第一个参数的位置
mem_fun_ref(&类名::函数名):注意其包含的函数只能有一个参数
步骤:
1,创建一个类
2,在该类中编写成员函数
3,使用算法,在算法适配器中使用mem_fun_ref包括该函数
注意:
集合中存储的对象所在的类与成员函数所在的类为同一个类
该函数必须是无参的
集合中获取的数据就是该类中的this
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
class Data
{
public:
int x;
Data(int x):x(x){ }
void my_method()
{
cout<<this->x<<endl;
}
};
int main()
{
list<Data> l;
l.push_back(Data(1));
l.push_back(Data(2));
l.push_back(Data(3));
l.push_back(Data(4));
for_each(l.begin(),l.end(),mem_fun_ref(&Data::my_method));
return 0;
}
取反适配器
not1 一元函数对象取反
not2 二元函数对象取反
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void show(int x)
{
cout<<x<<",";
}
bool compare(int x,int y)
{
return x<y;
}
class Myclass:public binary_function<int,int,bool>
{
public:
bool operator()(int x,int y)const
{
return x>y;
}
};
int main()
{
vector<int> nums;
nums.push_back(2);nums.push_back(1);nums.push_back(3);nums.push_back(6);nums.push_back(9);
for_each(nums.begin(),nums.end(),ptr_fun(show));
cout << endl;//查找 vector 中第一个大于 5 的值// vector<int>::iterator it =find_if(nums.begin(),nums.end(),bind2nd(ptr_fun(dy5),5));// auto it =find_if(nums.begin(),nums.end(),bind2nd(MyClass(),5));auto it =find_if(nums.begin(),nums.end(),not1(bind2nd(MyClass(),5)));cout << *it << endl;//排序算法sort(nums.begin(),nums.end(),not2(less<int>()));for_each(nums.begin(),nums.end(),ptr_fun(show));cout << endl;return 0;}
算法
遍历
for_each
/*遍历算法 遍历容器元素@param beg 开始迭代器@param end 结束迭代器@param _callback 函数回调或者函数对象@return 函数对象*/for_each(iterator beg, iterator end, _callback);
//基本使用#include <iostream>#include <deque>#incldue <algorithm>using namespace std;void myMethod(int x){cout<<x<<",";}int main(){deque<int> d;d.push_back(1);d.push_back(2);d.push_back(3);d.push_back(4);d.push_back(5);for_each(d.begin(),d.end(),myMthod);return 0;}
案例2:lamba表达式注意:c++11及以上版本才可使用作用:简化函数语法:[](形参列表){函数体}
#include <iostream>#include <deque>#include <algorithm>using namespace std;
void myMethod(int x){cout<<x<<",";}int mian(){deque<int> d;d.push_back(1);d.push_back(2);d.push_back(3);d.push_back(4);d.push_back(5);for_each(d.begin(),d.end(),[](int x){cout<<x<<",";});return 0;}
// 案例 3: 遍历存储自定义类型的集合class Data{private:int x;int y;public:Data(int x,int y):x(x),y(y){}void showData(){cout << "x = " << x << "\ty = " << y << endl;}};void fun02(){deque<Data> d;d.push_back(Data(1,11));d.push_back(Data(2,22));d.push_back(Data(3,33));for_each(d.begin(),d.end(),[](Data& data){data.showData();});}
transform
作用:搬运
语法:
/*
transform 算法 将指定容器区间元素搬运到另一容器中注意 :transform 不会给目标容器分配内存,所以需要我们提前分配好内存@param beg1 源容器开始迭代器@param end1 源容器结束迭代器@param beg2 目标容器开始迭代器@param _cakkback 回调函数或者函数对象@return 返回目标容器迭代器*/transform(iterator beg1, iterator end1, iterator beg2, _callbakc);/*transform 算法 将指定容器区间元素搬运到另一容器中注意:transform 不会给目标容器分配内存,所以需要我们提前分配好内存@param beg1 源容器 1 开始迭代器@param end1 源容器 1 结束迭代器@param beg2 源容器 2 开始迭代器@param result 结果@param _cakkback 回调函数或者函数对象@return 返回目标容器迭代器*/transform(iterator beg1, iterator end1, iterator beg2,iterator result, _callbakc);
#include <iostream>
#include <vector>#include <list>#include <algorithm>using namespace std;void fun01(){//定义一个容器存储员工的工资vector<double> mm;mm.push_back(2100);mm.push_back(21000);mm.push_back(6100);mm.push_back(4000);mm.push_back(16000);//本月工资涨 200list<double> ml;ml.resize(mm.size());transform(mm.begin(),mm.end(),ml.begin(),[](double x){return x+200;});for_each(ml.begin(),ml.end(),[](double m){cout << m << endl;});}int main(int argc, char const *argv[]){vector<double> mm;mm.push_back(2100);mm.push_back(21000);mm.push_back(6100);mm.push_back(4000);mm.push_back(16000);vector<double> mm02;mm02.push_back(210);mm02.push_back(2100);mm02.push_back(610);mm02.push_back(400);mm02.push_back(1600);vector<double> mm03;mm03.resize(mm.size());transform(mm.begin(),mm.end(),mm02.begin(),mm03.begin(),[](double x,double y){return x+y;});for_each(mm03.begin(),mm03.end(),[](double m){cout << m << endl;});return 0;}
查找算法
find
作用:查找/*find 算法 查找元素@param beg 容器开始迭代器@param end 容器结束迭代器@param value 查找的元素@return 返回查找到元素对应的迭代器*/find(iterator beg, iterator end, value)
void test01 (){vector < int > vs ;vs . push_back ( 12 );vs . push_back ( 15 );vs . push_back ( 11 );vs . push_back ( 13 );vs . push_back ( 14 );vector < int > :: iterator it = find ( vs . begin (), vs . end (), 13 );if ( it != vs . end ()){cout << " 找到了 " << endl ;}else {cout << " 不存在 " << endl ;}}
find_if
作用:条件查找
/*@param beg 容器开始迭代器@param end 容器结束迭代器@param callback 回调函数或者谓词 ( 返回 bool 类型的函数对象 )@return 返回查找到元素对应的迭代器*/find_if(iterator beg, iterator end, _callback)
bool myIf ( int x ){return x > 13 ;}void test02 (){vector < int > vs ;vs . push_back ( 12 );vs . push_back ( 15 );vs . push_back ( 11 );vs . push_back ( 13 );vs . push_back ( 14 );vector < int > :: iterator it = find_if ( vs . begin (), vs . end (), myIf );cout << * it << endl ;}
adjacent_find
作用:查找相邻重复元素
语法:
/***adjacent_find 算法 查找相邻重复元素*@param beg 容器开始迭代器*@param end 容器结束迭代器*@param _callback 回调函数或者谓词 ( 返回 bool 类型的函数对象 )*@return 返回相邻元素的第一个位置的迭代器**/adjacent_find(iterator beg, iterator end, _callback);10 20 30 30 40
示例:void test03 (){vector < int > vs ;vs . push_back ( 12 );vs . push_back ( 15 );vs . push_back ( 11 );vs . push_back ( 11 );vs . push_back ( 13 );vector < int > :: iterator it = adjacent_find ( vs . begin (), vs . end ());cout << * it << endl ;}
binary_search
作用:二分查找
语法:
/*注意 : 在无序序列中不可用@param beg 容器开始迭代器@param end 容器结束迭代器@param value 查找的元素@return bool 查找返回 true 否则 false*/bool binary_search(iterator beg, iterator end, value);
void test04 (){vector < int > vs ;vs . push_back ( 1 );vs . push_back ( 3 );vs . push_back ( 5 );vs . push_back ( 7 );vs . push_back ( 9 );bool b = binary_search ( vs . begin (), vs . end (), 7 );if ( b ){cout << " 存在 " << endl ;} else {cout << " 不存在 " << endl ;}}
count
作用:统计
语法:
/*@param beg 容器开始迭代器@param end 容器结束迭代器@param value 回调函数或者谓词 ( 返回 bool 类型的函数对象 )@return int 返回元素个数*/count(iterator beg, iterator end, value);
#include <set>void test05 (){multiset < int > s ;s . insert ( 1 );s . insert ( 2 );s . insert ( 2 );s . insert ( 2 );s . insert ( 5 );int num = count ( s . begin (), s . end (), 2 );cout << num << endl ;}
count_if
作用:条件统计
语法:
/*@param beg 容器开始迭代器@param end 容器结束迭代器@param callback 回调函数或者谓词 ( 返回 bool 类型的函数对象 )@return int 返回元素个数*/count_if(iterator beg, iterator end, _callback)
void test06 (){multiset < int > s ;s . insert ( 1 );s . insert ( 2 );s . insert ( 2 );s . insert ( 3 );s . insert ( 5 );//统计容器中大于 2 的数int num = count_if ( s . begin (), s . end (), bind2nd ( greater < int > (), 2 ));cout << num << endl ;//统计容器中小于 2 的数int num02 = count_if ( s . begin (), s . end (), bind2nd ( less < int > (), 2 ));cout << num02 << endl ;}
排序算法
merge
作用:合并
语法:
/*注意 : 两个容器必须是有序的@param beg1 容器 1 开始迭代器@param end1 容器 1 结束迭代器@param beg2 容器 2 开始迭代器@param end2 容器 2 结束迭代器@param dest 目标容器开始迭代器*/merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
void test01 (){vector < int > v1 ;v1 . push_back ( 1 );v1 . push_back ( 3 );v1 . push_back ( 5 );vector < int > v2 ;v2 . push_back ( 2 );v2 . push_back ( 4 );v2 . push_back ( 6 );vector < int > v3 ;v3 . resize ( v1 . size () + v2 . size ());merge ( v1 . begin (), v1 . end (), v2 . begin (), v2 . end (), v3 . begin ());for_each ( v3 . begin (), v3 . end (),[]( int x ){cout << x << " " ;});cout << endl ;}
sort
作用:排序
语法:
/*@param beg 容器 1 开始迭代器@param end 容器 1 结束迭代器@param _callback 回调函数或者谓词 ( 返回 bool 类型的函数对象 )*/sort(iterator beg, iterator end, _callback)
void test02 (){vector < int > vs ;vs . push_back ( 10 );vs . push_back ( 13 );vs . push_back ( 9 );vs . push_back ( 4 );vs . push_back ( 18 );for_each ( vs . begin (), vs . end (),[]( int x ){cout << x << " " ;});cout << endl ;// 默认从小到大sort ( vs . begin (), vs . end ());for_each ( vs . begin (), vs . end (),[]( int x ){cout << x << " " ;});cout << endl ;sort ( vs . begin (), vs . end (),[]( int x , int y ){return x > y ;});for_each ( vs . begin (), vs . end (),[]( int x ){cout << x << " " ;});cout << endl ;}
random_shuffle
作用:打乱
语法:
/*@param beg 容器开始迭代器@param end 容器结束迭代器*/random_shuffle(iterator beg, iterator end)
void test04 (){vector < int > vs ;vs . push_back ( 1 );vs . push_back ( 2 );vs . push_back ( 3 );vs . push_back ( 4 );vs . push_back ( 5 );random_shuffle ( vs . begin (), vs . end ());for_each ( vs . begin (), vs . end (),[]( int x ){cout << x << " " ;});cout << endl ;}
reverse
作用:翻转
语法:
/*@param beg 容器开始迭代器@param end 容器结束迭代器*/reverse(iterator beg, iterator end)
void test05 (){vector < int > vs ;vs . push_back ( 31 );vs . push_back ( 2 );vs . push_back ( 23 );vs . push_back ( 14 );vs . push_back ( 5 );sort ( vs . begin (), vs . end ());for_each ( vs . begin (), vs . end (),[]( int x ){cout << x << " " ;});cout << endl ;reverse ( vs . begin (), vs . end ());for_each ( vs . begin (), vs . end (),[]( int x ){cout << x << " " ;});cout << endl ;}
拷贝与替换
copy
作用:拷贝
语法:
/*@param beg 容器开始迭代器@param end 容器结束迭代器@param dest 目标起始迭代器*/copy(iterator beg, iterator end, iterator dest)
void test01(){vector<int> vs;vs.push_back(31);vs.push_back(2);vs.push_back(23);vs.push_back(14);vs.push_back(5);vector<int> newVs;newVs.resize(vs.size());copy(vs.begin(),vs.end(),newVs.begin());for_each(newVs.begin(),newVs.end(),[](int x){cout << x << endl;});}
replace
作用:替换
语法:
/*@param beg 容器开始迭代器@param end 容器结束迭代器@param oldvalue 旧元素@param oldvalue 新元素*/replace(iterator beg, iterator end, oldvalue, newvalue)
void test02 (){vector < int > vs ;vs . push_back ( 31 );vs . push_back ( 2 );vs . push_back ( 23 );vs . push_back ( 14 );vs . push_back ( 5 );replace ( vs . begin (), vs . end (), 2 , 20 );for_each ( vs . begin (), vs . end (),[]( int x ){cout << x << endl ;});}
replace_if
作用:条件替换
/*@param beg 容器开始迭代器@param end 容器结束迭代器@param callback 函数回调或者谓词 ( 返回 Bool 类型的函数对象 )@param oldvalue 新元素*/replace_if(iterator beg, iterator end, _callback, newvalue)
void test03 (){vector < int > vs ;vs . push_back ( 31 );vs . push_back ( 2 );vs . push_back ( 23 );vs . push_back ( 14 );vs . push_back ( 5 );replace_if ( vs . begin (), vs . end (),[]( int x ){return x < 20 ;}, 20 );for_each ( vs . begin (), vs . end (),[]( int x ){cout << x << endl ;});}
swap
作用:交换
语法:
/*@param c1 容器 1@param c2 容器 2*/swap(container c1, container c2)
void test04 (){vector < int > v01 ;v01 . push_back ( 1 );v01 . push_back ( 2 );v01 . push_back ( 3 );v01 . push_back ( 4 );v01 . push_back ( 5 );vector < int > v02 ;v02 . push_back ( 6 );v02 . push_back ( 7 );v02 . push_back ( 8 );cout << " 交换前 :" << endl ;for_each ( v01 . begin (), v01 . end (),[]( int x ){cout << x << " " ;});cout << endl ;for_each ( v02 . begin (), v02 . end (),[]( int x ){cout << x << " " ;});cout << endl ;swap ( v01 , v02 );cout << " 交换后 :" << endl ;for_each ( v01 . begin (), v01 . end (),[]( int x ){cout << x << " " ;});cout << endl ;for_each ( v02 . begin (), v02 . end (),[]( int x ){cout << x << " " ;});cout << endl ;}
常用算数生成算法
accumulate
作用:计算容器内元素累计总和
语法:
/*@param beg 容器开始迭代器@param end 容器结束迭代器@param value 累加值@return int 总和*/accumulate(iterator beg, iterator end, value)
void test01 (){vector < int > v01 ;v01 . push_back ( 1 );v01 . push_back ( 2 );v01 . push_back ( 3 );v01 . push_back ( 4 );v01 . push_back ( 5 );int sum = 0 ;sum = accumulate ( v01 . begin (), v01 . end (), 0 );cout << sum << endl ;}
fill
作用 : 指定的值赋给指定范围内的所有元素语法:/*@param beg 容器开始迭代器@param end 容器结束迭代器@param value t 填充元素*/fill(iterator beg, iterator end, value)
void test02()
{vector<int> v01;v01.push_back(1);v01.push_back(2);v01.push_back(3);v01.push_back(4);v01.push_back(5);fill(v01.begin(),v01.end(),10);for_each(v01.begin(),v01.end(),[](int x){cout << x << " ";});cout << endl;}
set_intersection
作用:获取交集
语法:
/*注意 : 两个集合必须是有序序列@param beg1 容器 1 开始迭代器@param end1 容器 1 结束迭代器@param beg2 容器 2 开始迭代器@param end2 容器 2 结束迭代器@param dest 目标容器开始迭代器@return 目标容器的最后一个元素的迭代器地址*/set_intersection(iterator beg1, iterator end1, iterator beg2, iteratorend2, iterator dest)
void test03(){vector<int> v01;v01.push_back(1);v01.push_back(2);v01.push_back(3);v01.push_back(4);v01.push_back(5);vector<int> v02;v02.push_back(1);v02.push_back(4);v02.push_back(7);vector<int> v03;//back_inserter: 获取一个插入迭代器set_intersection(v01.begin(),v01.end(),v02.begin(),v02.end(),back_inserter(v03));for_each(v03.begin(),v03.end(),[](int x){cout << x << " ";});cout << endl;}
set_union
作用:获取并集
语法:
/*注意 : 两个集合必须是有序序列@param beg1 容器 1 开始迭代器@param end1 容器 1 结束迭代器@param beg2 容器 2 开始迭代器@param end2 容器 2 结束迭代器@param dest 目标容器开始迭代器@return 目标容器的最后一个元素的迭代器地址*/set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
void test04(){vector<int> v01;v01.push_back(1);v01.push_back(2);v01.push_back(3);v01.push_back(4);v01.push_back(5);vector<int> v02;v02.push_back(1);v02.push_back(4);v02.push_back(7);vector<int> v03;//back_inserter: 获取一个插入迭代器set_union(v01.begin(),v01.end(),v02.begin(),v02.end(),back_inserter(v03));for_each(v03.begin(),v03.end(),[](int x){cout << x << " ";});cout << endl;}
set_difference
作用:取差集
差集 :A 与 B 的差集 , 就是 A 中有 B 中没有的元素集合 , 反之 B 与 A 取差集 , 就是 B 中有 A 中没有的元素集合语法:/*注意 : 两个集合必须是有序序列@param beg1 容器 1 开始迭代器@param end1 容器 1 结束迭代器@param beg2 容器 2 开始迭代器@param end2 容器 2 结束迭代器@param dest 目标容器开始迭代器@return 目标容器的最后一个元素的迭代器地址*/set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
void test05 (){vector < int > v01 ;v01 . push_back ( 1 );v01 . push_back ( 3 );v01 . push_back ( 5 );v01 . push_back ( 7 );v01 . push_back ( 9 );vector < int > v02 ;v02 . push_back ( 9 );v02 . push_back ( 11 );v02 . push_back ( 13 );vector < int > v03 ;//back_inserter: 获取一个插入迭代器set_difference ( v01 . begin (), v01 . end (), v02 . begin (), v02 . end (), back_inserter ( v03 ));for_each ( v03 . begin (), v03 . end (),[]( int x ){cout << x << " " ;});cout << endl ;}