仿函数
来源:互联网 发布:酒店软件排名 编辑:程序博客网 时间:2024/04/29 15:45
仿函数三大妙处:
1、仿函数比一般函数更灵巧,因为它可以拥有状态。事实上对于仿函数,你可以同时拥有两个状态不同的实体。
2、每个仿函数都有其型别。因为你可以将仿函数的型别当作template参数来传递,从而指定某种行为模式,容器型别也会因为仿函数的不同而不同。
3、执行速度上,仿函数通常比函数指针更快。就template概念而言,很多细节在编译期就已确定。
仿函数是以by value方式传递的好处是,你可以传递常量或暂时表达式,如果不这样设计,就不能传递ClassName(1)这样的表达式(临时对象),至于缺点是无法改变仿函数的状态。因为你改变的只是副本而已。然而我们有时候确实需要存取最终状态。因此,问题在于如何从一个算法中获取结果。
有两个办法可以从“运用了仿函数”的算法中获取“结果”或“反馈”。
1、以by reference的方式传递仿函数(仅限参考,不一定管用)
2、运用for_each()算法的回返值
例1:by reference(在vs2013上不管用,原因如注释)
#include <iostream>#include <list>#include<algorithm>#include<iterator>using namespace std;class IntSequence{private:int value;public:IntSequence(int initialValue) :value(initialValue){};int operator()(){return value++;}};int main(){list<int> coll;IntSequence seq(1);generate_n<back_insert_iterator<list<int>>, int, IntSequence&>(back_inserter(coll), 4, seq);//在该算法内部,调用了另外的模板 //进行了传值,而不是by referencecopy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));cout << endl;generate_n(back_inserter(coll), 4, IntSequence(42));generate_n(back_inserter(coll), 4, seq);copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));cout << endl;system("pause");return 0;}
例2:for_each()
#include <iostream>#include <vector>#include<algorithm>#include<iterator>using namespace std;class MeanValue{private:long num;long sum;public:MeanValue() :num(0), sum(0){}void operator()(int elem){num++;sum += elem;}double value(){return static_cast<double>(sum) / static_cast<double>(num);}};int main(){vector<int> coll;for (int i = 1; i <= 8; ++i){coll.push_back(i);}MeanValue mv = for_each(coll.begin(), coll.end(), MeanValue());cout <<"mean value"<<mv.value()<< endl;system("pause");return 0;}
输出:mean value4.5
一个陷阱:
#include <iostream>#include <list>#include<algorithm>#include<iterator>using namespace std;class Nth{private:int nth;int count;public:Nth(int n) :nth(n), count(0){}bool operator()(int){return ++count == nth;}};int main(){list<int> coll;for (int i = 1; i <= 9; ++i){coll.push_back(i);}copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));cout << endl;list<int>::iterator pos;pos = remove_if(coll.begin(), coll.end(), Nth(3));coll.erase(pos, coll.end());copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));cout << endl;system("pause");return 0;}
输出:
1 2 3 4 5 6 7 8 9
1 2 4 5 7 8 9 //3和6都被删除了
下面是remove_if的一般实作:
template<class ForwIter,class Predicate>ForwIter std::remove_if(ForwIter beg, ForwIter end, Predicate op){ beg = find_if(beg, end, op); if (beg == end) { return beg; } else { ForwIter next = beg; return remove_copy_if(++next, end, beg, op); }}
find_if传值,remove_copy_if中op的count从零开始,即在实施删除时又进行了一次删除。
解决方法:总是将判断式operator()声明为const成员函数。
预定义的仿函数:
#include<functional>
仿函数
效果
negate<type>()
-param
plus<type>()
param1+param2
minus<type>()
param1-param2
multiplies<type>()
param1*param2
divides<type>()
param1/param2
modulus<type>()
param1%param2
equal_to<type>()
param1==param2
not_equal_to<type>()
param!=param2
less<type>()
param1<param2
greater<type>()
param1>param2
less_equal<type>()
param1<=param2
greater_equal<type>()
param1>=param2
logical_not<type>()
!param
logical_and<type>()
param1&¶m2
logical_or<type>()
param1||param2
函数配接器:
表达式
效果
bind1st(op,value)
op(value,param)
bind2nd(op,value)
op(param,value)
not1
!op(param)
not2
!op(param1,param2)
针对成员函数而设计的函数配接器
mem_fun_ref(op)
调用op,那是某对象的一个const成员函数
mem_fun(op)
调用op,那是某对象指针的一个const成员函数
针对一般函数而设计的函数配接器
ptr_fun(op)
op(param)
op(param1,param2)
例子:mem_fun_ref
vs2013不要求成员函数为const
</pre><pre class="cpp" name="code">class Person{private:string name;public:Person(string na) :name(na){}void print() const{cout << name << endl;}void printWithPrefix(string prefix)const{cout << prefix << name << endl;}};list<Person> coll;for_each(coll.begin(), coll.end(), mem_fun_ref(&Person::print));for_each(coll.begin(), coll.end(), bind2nd(mem_fun_ref(&Person::printWithPrefix), "person:"));
list<Person*> coll;for_each(coll.begin(), coll.end(), mem_fun(&Person::print));for_each(coll.begin(), coll.end(), bind2nd(mem_fun(&Person::printWithPrefix), "person:"));
mem_fun_ref和mem_fun两者都能以无参数或单参数方式来调用成员函数。
ptr_fun:
假设有一个能对每个参数实施某种检测的全局函数如下:
bool check(int elem)
如果要搜寻第一个令检查失败的元素,可以如下:
pos=find_if(coll.begin(),coll.end(),not1(ptr_fun(check)));
这里ptr_fun不可省略,因为not1()需要用到仿函数提供的某些特殊型别。
第二种用法,你有一个双参数全局函数,又想把它当成一个单参数函数使用
pos=find_if(coll.begin(),coll.end(),bind2nd(ptr_fun(strcmp),""));
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- 仿函数
- android strings.xml转义字符, 注意细节解决
- 驱动开发之 用DeviceIoControl实现应用程序与驱动程序通信
- 程序员保持天天快乐的6个习惯
- 使用VMWare虚拟机创建CentOS版本的Linux学习环境(每一步都有截图与说明)
- 闪存分析教程及其优点的用法
- 仿函数
- 【Unity 3D】学习笔记四十:射线
- 黑马程序员-C语言学习-函数
- stm32 usb host移植
- QT 实现QLabel上的超链接
- table排序
- 钐分析随着钐分析工具
- 闪存Analytics(分析)和网上市场的需求
- Cacti监控snmpd服务的设置