zoukankan      html  css  js  c++  java
  • 仿函数

    仿函数三大妙处:

    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 reference
    	copy(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&&param2

    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),""));
  • 相关阅读:
    linux下启动和关闭网卡命令及DHCP上网
    python 编码问题
    paddlepaddle
    Convolutional Neural Network Architectures for Matching Natural Language Sentences
    deep learning RNN
    Learning Structured Representation for Text Classification via Reinforcement Learning 学习笔记
    Python IO密集型任务、计算密集型任务,以及多线程、多进程
    EM 算法最好的解释
    tensorflow 调参过程
    tensorflow 学习纪录(持续更新)
  • 原文地址:https://www.cnblogs.com/ggzone/p/10121346.html
Copyright © 2011-2022 走看看