赞
踩
重载函数调用操作符的类,其对象常称为函数对象,即他们是行为类似函数的对象。一个类对象,表现出一个函数的特征,就是通过 ”对象名+(参数列表)“ 的方式使用一个类对象,如果没有上下文,完全可以把他看做一个函数对待。
函数对象和普通函数的异同:
#include<iostream> using namespace std; //函数对象 类重载了() template <typename T> class ShowElemt { public: void operator()(T& t) { cout << t << endl; } }; //函数模板 template <typename T> void FuncShowElemt(T& t) { cout << t << endl; } //普通函数 void FuncShowElemt2(int& t) { cout << t << endl; } int main() { int a = 10; ShowElemt<int> s1; s1(a); FuncShowElemt<int>(a); FuncShowElemt2(a); return 0; }
函数对象是属于类对象的,能突破函数的概念,能保持调用状态信息。
#include<iostream> using namespace std; #include<vector> #include<algorithm> //函数对象 类重载了() template <typename T> class ShowElemt { public: ShowElemt() { n = 0; } void operator()(T& t) { n++; cout << t << endl; } int n; } //函数模板 template <typename T> void FuncShowElemt(T& t) { cout << t << endl; } //普通函数 void FuncShowElemt2(int& t) { cout << t << endl; } int main() { vector<int> v1; v1.push_back(1); v1.push_back(2); v1.push_back(3); ShowElemt<int> s1; for_each(v1.begin(), v1.end(), s1);//匿名函数对象 匿名仿函数 cout << s1.n << endl;//0 s1 = for_each(v1.begin(), v1.end(), s1);//匿名函数对象 匿名仿函数 cout << s1.n << endl;//3 for_each(v1.begin(), v1.end(), FuncShowElemt2);//通过回调函数 谁使用for_each 谁去填写回调函数的入口地址 return 0; }
//for_each 函数原型:
_EXPORT_STD template <class _InIt, class _Fn>
_CONSTEXPR20 _Fn for_each(_InIt _First, _InIt _Last, _Fn _Func) { // perform function for each element [_First, _Last)
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst) {
_Func(*_UFirst);
}
return _Func;
}
函数对象 对比 普通函数:函数对象可以保存调用的信息。
通过for_each函数原型可以看出,函数对象的传递并非引用,但是会返回函数对象。
一元函数对象:函数参数1个
二元函数对象:函数参数2个
一元谓词 函数参数1个,函数返回值是bool类型,可以作为一个判断式
谓词可以是一个仿函数,也可以是一个回调函数。
例子:
#include<iostream> using namespace std; #include<vector> template<typename T> class IsDev { public: IsDev(const T n) { this->n = n; } bool operator()(T &n) { if (n == this->n) return true; return false; } T n; }; int main() { vector<int> v1; for (int i = 1; i <= 10; i++) { v1.push_back(i); } int a = 4; vector<int>::iterator it = find_if(v1.begin(), v1.end(), IsDev<int>(a)); if (it != v1.end()) { cout << *it << endl; } else { cout << "false" << endl; } return 0; }
#include<iostream> using namespace std; #include<vector> #include<algorithm> template<typename T> class SumAdd { public: T operator()(T &a,T &b) { return a + b; } }; /* 两种方式 方式二 template<typename T> T SumAdd(T a, T b) { return a + b; }*/ //二元谓词 int main() { /* _EXPORT_STD template <class _InIt1, class _InIt2, class _OutIt, class _Fn> _CONSTEXPR20 _OutIt transform( const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _OutIt _Dest, _Fn _Func) { // transform [_First1, _Last1) and [_First2, ...) with _Func _Adl_verify_range(_First1, _Last1); auto _UFirst1 = _Get_unwrapped(_First1); const auto _ULast1 = _Get_unwrapped(_Last1); const auto _Count = _Idl_distance<_InIt1>(_UFirst1, _ULast1); auto _UFirst2 = _Get_unwrapped_n(_First2, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2, ++_UDest) { *_UDest = _Func(*_UFirst1, *_UFirst2); } _Seek_wrapped(_Dest, _UDest); return _Dest; } */ // v1 + v2 ==> v3 vector<int> v1, v2, v3; v1.push_back(1); v1.push_back(3); v1.push_back(5); v2.push_back(2); v2.push_back(4); v2.push_back(6); v3.resize(10); transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), SumAdd<int>()); //transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), SumAdd<int>);//方式二 for (vector<int>::iterator it = v3.begin(); it != v3.end();it++) { cout << *it << " "; } cout << endl; return 0; }
#include<iostream> using namespace std; #include<vector> #include<algorithm> template<typename T> void show(T &a) { cout << a << " "; } bool myCompare(int a, int b) { return a > b; } int main() { vector<int> v1(10); for (int i = 0; i < 10; i++) { int temp = rand() % 100; v1[i] = temp; } for_each(v1.begin(), v1.end(), show<int>);//遍历 cout << endl; sort(v1.begin(), v1.end(), myCompare);//排序 for_each(v1.begin(), v1.end(), show<int>);//遍历 cout << endl; return 0; }
标准模版库 stl 提前定义了很多预定义的函数对象,#include<functional> 要包含(不包含也行。。)。
#include<iostream> using namespace std; #include<functional> int main() { plus<int> intAdd; int s = intAdd(10, 20); cout << s << endl;//30 plus<string> strAdd; string str = strAdd("a", "b"); cout << str << endl;//ab return 0; }
算术函数对象:
加法:plus<Types>
plus<string> stringAdd;
sres = stringAdd(sva1,sva2);
减法:minus<Types>
乘法:multiplies<Types>
除法divides<Tpye>
求余:modulus<Tpye>
取反:negate<Type>
negate<int> intNegate;
ires = intNegate(ires);
Ires= UnaryFunc(negate<int>(),Ival1);
关系函数对象
等于equal_to<Tpye>
equal_to<string> stringEqual;
sres = stringEqual(sval1,sval2);
不等于not_equal_to<Type>
大于 greater<Type>
大于等于greater_equal<Type>
小于 less<Type>
小于等于less_equal<Type>
逻辑函数对象
逻辑与 logical_and<Type>
logical_and<int> indAnd;
ires = intAnd(ival1,ival2);
dres=BinaryFunc( logical_and<double>(),dval1,dval2);
逻辑或logical_or<Type>
逻辑非logical_not<Type>
logical_not<int> IntNot;
Ires = IntNot(ival1);
Dres=UnaryFunc( logical_not<double>,dval1);
实例:
#include<iostream> using namespace std; #include<vector> #include<algorithm> //#include<functional> template<typename T> void show(T &a) { cout << a << " "; } int main() { vector<string> v1; v1.push_back("bbb"); v1.push_back("aaa"); v1.push_back("ddd"); v1.push_back("ccc"); sort(v1.begin(), v1.end(), greater<string>()); for_each(v1.begin(), v1.end(), show<string>);//遍历 return 0; }
stl 中已经定义了大量的函数对象,但是有时候需要对函数返回值进行进一步的简单计算,或者填上多余的参数,不能直接带入算法。函数适配器实现了这一功能,将一种函数对象转化为另一种符合要求的函数对象。
函数适配器可以分为4大类:
常用函数适配器:
bind1st(op, value)
bind2nd(op,value)
not1(op)
not2(op)
例子:
#include<iostream> using namespace std; #include<vector> #include<algorithm> #include<functional> class IsGreat { public: IsGreat(int i) { n = i; } bool operator()(int i) { return i > n; } int n; }; int main() { vector<int> v1; for (int i = 0; i < 10; i++) { v1.push_back(i + 1); } //通过 谓词 求大于2 的个数 int num = count_if(v1.begin(), v1.end(), IsGreat(2)); cout << num << endl;//8 //通过 预定于的函数对象 求大于2 的个数 //greater<int>()有两个参数 左参数来自容器的元素,右参数固定成2(通过bind2nd做的) int num2 = count_if(v1.begin(), v1.end(), bind2nd(greater<int>(), 2)); cout << num2 << endl;//8 //求 奇数的个数 int num3 = count_if(v1.begin(), v1.end(), bind2nd(modulus<int>(), 2)); cout << num3 << endl;//5 //求 偶数的个数 (求奇数取反) int num4 = count_if(v1.begin(), v1.end(), not1(bind2nd(modulus<int>(), 2))); cout << num4 << endl;//5 }
stl 的容器通过类模版技术,实现数据类型和容器模型的分离
stl 的迭代器技术 实现了 遍历容器 的统一方法;也为 stl 的算法提供了统一性奠定了基础
stl 的算法,通过函数对象 实现了 自定义数据类型 的算法运算;所以说:stl 的算法也提供了统一性
核心思想:其实函数对象本质就是 回调函数,回调函数的思想:就是任务的编写者和任务的调用者有效解耦合。函数指针做函数参数。
具体例子:transform 算法的输入,通过迭代器 first和last 指向的元素作为输入;通过result 作为输出;通过函数对象来做自定义数据类型的运算。
操作对象:
功能:
for_each() 速度快 不灵活
transform() 速度慢 非常灵活
for_each 所使用的函数对象,参数是引用,没有返回值
transform所使用的函数对象,参数一般不适用引用,而是还有返回值
例子:
#include<iostream> using namespace std; #include<vector> #include<algorithm> #include<functional> template <typename T> void printV(vector<T>& v) { for (auto it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } // for_each 遍历 与 transform 区别 template <typename T> void showV(T &n) { cout << n << " "; } template <typename T> T showV2(T& n) { cout << n << " "; return n; } template <typename T> class showElemt { public: void operator()(T &n){ cout << n << " "; } }; int increase(int i) { return i+100; } int main() { vector<int> v1; v1.push_back(1); v1.push_back(3); v1.push_back(5); printV<int>(v1); //for_each for_each(v1.begin(), v1.end(), showV<int>); cout << endl; for_each(v1.begin(), v1.end(), showElemt<int>()); cout << endl; //transform 回调函数 transform(v1.begin(), v1.end(), v1.begin(), increase); printV<int>(v1); //transform 预定义 transform(v1.begin(), v1.end(), v1.begin(), negate<int>()); printV<int>(v1); //transform 函数适配器 transform(v1.begin(), v1.end(), v1.begin(), bind2nd(multiplies<int>(),10)); printV<int>(v1); //transform 把运算结果直接输出到屏幕 transform(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "), negate<int>()); cout << endl; //transform 遍历 与 for_each 区别 //transform(v1.begin(), v1.end(), v1.begin(), showV<int>);//error transform(v1.begin(), v1.end(), v1.begin(), showV2<int>); cout << endl; printV<int>(v1); //other.. vector<string> v2; v2.push_back("aaa"); v2.push_back("bbb"); v2.push_back("ccc"); printV<string>(v2); //for_each for_each(v2.begin(), v2.end(), showV<string>); cout << endl; for_each(v2.begin(), v2.end(), showElemt<string>()); cout << endl; return 0; }
transform 源码原型:
_EXPORT_STD template <class _InIt, class _OutIt, class _Fn>
_CONSTEXPR20 _OutIt transform(const _InIt _First, const _InIt _Last, _OutIt _Dest, _Fn _Func) {
// transform [_First, _Last) with _Func
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast));
for (; _UFirst != _ULast; ++_UFirst, (void) ++_UDest) {
*_UDest = _Func(*_UFirst);//关键所在:解释了为什么要有返回值。
}
_Seek_wrapped(_Dest, _UDest);
return _Dest;
}
#include<iostream> using namespace std; #include<vector> #include<algorithm> //count_if 条件函数 bool GreaterThree(int num) { return num > 3; } //find_if bool IsTwo(int num) { return num == 2; } int main() { vector<int> v1; v1.push_back(1); v1.push_back(2); v1.push_back(2); v1.push_back(3); // adjacent_find 查到第一个重复的元素 vector<int>::iterator it = adjacent_find(v1.begin(), v1.end()); if (it != v1.end()) { cout << *it << endl;//2 } int index = distance(v1.begin(), it); cout << index << endl;//1 //binary_search 二分查找 速度快 bool b = binary_search(v1.begin(), v1.end(), 2); if (b) { cout << "has" << endl;//has } //count 相等个数 int iCount = count(v1.begin(), v1.end(), 2); cout << iCount << endl;//2 //count_if 先定义比较函数 int iCount_if = count_if(v1.begin(), v1.end(), GreaterThree); cout << iCount_if << endl;//0 //find 查找第一个元素位置 vector<int>::iterator it1 = find(v1.begin(), v1.end(), 2); while (it1 != v1.end()) { cout << *it1 << " ";//2 2 3 it1++; } cout << endl; //find_if 查找符合函数的第一个元素位置 vector<int>::iterator it2 = find_if(v1.begin(), v1.end(), IsTwo); while (it2 != v1.end()) { cout << *it2 << " ";//2 2 3 it2++; } cout << endl; return 0; }
#include<iostream> using namespace std; #include<vector> #include<algorithm> void printV(vector<int> v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } int main() { vector<int> v1; v1.push_back(5); v1.push_back(3); v1.push_back(1); vector<int> v2; v2.push_back(6); v2.push_back(4); v2.push_back(2); vector<int> v3; v3.resize(v1.size() + v2.size()); //sort 排序(默认升序) sort(v1.begin(), v1.end()); printV(v1); sort(v2.begin(), v2.end()); printV(v2); //merge 将两个有序容器合一 无序会error(还要升序,用之前先sort()一下) merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin()); printV(v3); //random_shuffle 随机排序 srand(time(0));//设置随机种子(没:每次结果都一样) random_shuffle(v3.begin(), v3.end()); printV(v3); string str("hello world!"); random_shuffle(str.begin(), str.end()); cout << str << endl; sort(v3.begin(), v3.end());//重新排序 //reverse 倒序 reverse(v3.begin(), v3.end()); printV(v3); return 0; }
#include<iostream> using namespace std; #include<vector> #include<algorithm> void printV(vector<int> v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } bool GreaterFive(int num) { return num > 5; } int main() { vector<int> v1; v1.push_back(1); v1.push_back(3); v1.push_back(3); v1.push_back(5); v1.push_back(7); vector<int> v2; v2.resize(v1.size()); //copy 拷贝 copy(v1.begin(), v1.end(), v2.begin()); printV(v2); //replace 替换 replace(v1.begin(), v1.end(), 3, 8); printV(v1); //replace 根据条件替换 replace_if(v1.begin(), v1.end(), GreaterFive, 3); printV(v1); //swap 交换 vector<int> v3; v3.push_back(2); v3.push_back(4); v3.push_back(6); swap(v1, v3); printV(v1);//2 4 6 return 0; }
#include<iostream> using namespace std; #include<vector> #include<numeric> void printV(vector<int> v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } int main() { vector<int> v1; v1.push_back(1); v1.push_back(3); v1.push_back(5); v1.push_back(7); //accumulate 容器值先相加,再加上10 int iSum = accumulate(v1.begin(), v1.end(), 10); cout << iSum << endl;//26 //fill 将容器中所以值改成 10 fill(v1.begin(), v1.end(), 10); printV(v1); return 0; }
#include<iostream> using namespace std; #include<vector> #include<algorithm> void printV(vector<int> v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } int main() { vector<int> v1; v1.push_back(1); v1.push_back(3); v1.push_back(5); vector<int> v2; v2.push_back(1); v2.push_back(3); v2.push_back(6); vector<int> v3; v3.resize(v1.size() + v2.size()); //set_union 两个有序序列的并集 set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin()); printV(v3);//1 3 5 6 fill(v3.begin(), v3.end(), 0);//置0 //set_intersection 两个有序序列的交集 set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin()); printV(v3);//1 3 fill(v3.begin(), v3.end(), 0);//置0 //set_difference 第一个序列存在,而第二个序列没有的 set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin()); printV(v3);//5 return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。