锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

C++【STL】 | 仿函数的应用以及如何规范要求

时间:2023-04-26 15:07:00 w轴向位移变送器配接ws

文章目录

    • 一、基本概念
      • 1.1 为什么有仿函数?这样做有什么好处?
      • 1.2 为什么可以使用仿函数?
      • 1.3 仿函数的内部状态?
        • 1.3.1 pass by value
        • 1.3.3 pass by reference
        • 1.3.4 for_each的回返值
    • 三、判断和仿函数
      • 3.1 基本概念
      • 3.2 判断不应被调用来改变自己的状态
    • 四、STL中标准仿函数
      • 4.1 满足STL仿函数的要求是什么?
      • 4.2 STL中的identity、select、project仿函数
      • 4.3 常用仿函数

一、基本概念

就是让一个类的使用看起来像一个类函数。实际上,实现就是实现一个类operator(),这一类有类似函数的行为,即仿函数类;

class Func { 
         public:  void operator() () const { 
           statements;  } }; 

1.1 为什么有仿函数?这样做有什么好处?

STL仿函数也涉及很多,有时使用仿函数是为了函数为了实现安全传性质函数指针依据函数生成对象、甚至在函数之间继承关系,函数运算操作的效果;

//less的定义 template<typename _Tp>  struct less : public binary_function<_Tp, _Tp, bool> { 
               bool operator()(const _Tp& __x, const _Tp& __y) const        { 
         return __x < __y; } };   //set的申明 template<typename _Key,      typename _Compare = std::less<_Key>,     typename _Alloc = std::allocator<_Key>> class set; 
  • 比一般函数灵巧,可拥有状态;对于仿函数,可同时拥有两个状态不同的实体;
  • 每个仿函数都有其型别,可使用template来传参
  • 阔以使用内联函数,执行速度通常比函数指针更快
  • 阔以使用成员变量,以免去对一些公共变量的维护,也可以使重复使用的代码独立出来;
  • 也阔以进行依赖组合继承

1.2 仿函数可作为什么?

在开发过程经常需要使用已序的对象置于容器中,但我们一般不使用operator来排序,从而使用仿函数来操作;

class FuncSort { 
        
public:
	/** 可自定义排序准则 */
	void operator() (const Person& p2) const { 
        
		return num < p2.num;
	}
};

1.3 仿函数的内部状态?

/*---------------------------------------------------------------------- > File Name: test.cpp > Author: Jxiepc > Mail: Jxiepc > Created Time: Mon 07 Mar 2022 04:08:01 PM CST ----------------------------------------------------------------------*/

#include 
#include 
#include 

class Func { 
        
    public:
        Func(int val) : m_val(val) { 
        
        }

        int operator() () { 
        
            return m_val++;
        }
    private:
        int m_val;
};

int main(int argc, char* argv[])
{ 
        
    std::list<int> coll;
    std::generate_n(std::back_inserter(coll),
            9,
            Func(4));

    for(auto& i:coll) { 
        
        std::cout << i << " ";
    }
    std::cout <<  std::endl;
    return 0;
}

在这里插入图片描述

根据以上实例,仿函数可维持内部val的数值,进而叠加

1.3.1 pass by value

当使用传值时,算法不会改变随参数而来的仿函数状态,若改变只是其中的副本

int main(int argc, char* argv[])
{ 
        
    std::list<int> coll;
	Func f(1);
	std::generate_n(std::back_inserter(coll),
       		9,
       		f);
	std::generate_n(std::back_inserter(coll),
       		9,
       		f);
    for(auto& i:coll) { 
        
        std::cout << i << " ";
    }
    std::cout << std::endl;
    return 0;
}

1.3.3 pass by reference

当使用引用传参(或使用for_each)时,即可从中获取结果反馈

int main(int argc, char* argv[])
{ 
        
    std::list<int> coll;
	Func f(1);
	std::generate_n<std::back_insert_iterator<std::list<int> >, int, Func&> (std::back_inserter(coll), 9, f);
	std::generate_n(std::back_inserter(coll),
       		9,
       		f);
    for(auto& i:coll) { 
        
        std::cout << i << " ";
    }
    std::cout << std::endl;
    return 0;
}

1.3.4 for_each的回返值

出现了该函数可代替引用传参的方式,来获取存储的最终状态

// 返回值为仿函数类型,在仿函数内部提供一个状态返回即可通过该返回值进行查询;
template<typename InputIterator, typename Function>
Function for_each(InputIterator beg, InputIterator end, Function f) { 
        
  while(beg != end) 
    f(*beg++);
}

三、判断式与仿函数

3.1 基本概念

即返回布尔值的一个函数或者仿函数;

3.2 判断式不应该被调用而改变自身的状态

为了保证这一点需要将operator声明为const成员函数

四、STL中标准仿函数

其中通过操作数进行划分为一元和二元,通过功能划分为算术、关系、逻辑运算;

4.1 满足STL的仿函数需要有哪些要求呢

必须定义相应的型别,为了让配置器能够萃取出类型;
该型别通过typedef设定,该操作于编译器即完成,不会影响效率及带来负担;
需要的型别有哪些呢?STL提供了unary_function和binary_function分别为一元二元的型别;

unarg_function

template<class Arg, class Result>
struct unary_function { 
        
	typedef Arg argument_type;
	typedef Result result_type;
};

binary_function

template<class Arg1, class Arg2, class Result>
struct binary_function { 
        
	typedef Arg1 first_argument_type;
	typedef Arg2 second_argument_type;
	typedef Result result_type;
};

这些型别在我们真正使用仿函数时一般用不到,那用在何处呢???

一般用在适配器上;
template<class Operation>
class binder1st { 
        
protected:
	Operation op;
	typename Operation::first_argument_type value;
public:
	typename Operation::result_type operator()(const typename Opreator::second_argument_type& x) const { 
        
		// ....
	}
};

4.2 STL中的identity、select、project仿函数

此类函数为STL了提供了间接性;
【identity】:证同函数,数值通过该函数,不会有任何变化;使用在map、set中告诉该类key如何得到;
【select】:选择函数,接收pair返回第一个或第二个参数;
【project】:投射函数,传回第一个或第二参数;

identity

template<class T>
struct identity : public unary_function<T, T> { 
        
    const T& operator()(const T& x) const { 
         return x; }
};

select

template<class Pair>
struct select1st : public unary_function<Pair, typename Pair::first_type>{ 
        
    const typename Pair::first_type& operator()(const Pair& x) const { 
        
        return x.first;
    }
};

template<class Pair>
struct select2nd : public unary_function<Pair, typename Pair::second_type>{ 
        
    const typename Pair::second_type& operator()(const Pair& x) const { 
        
        return x.seond;
    }
};

project

template<class Args1, class Args2>
struct project1st : public binary_function<Args1, Args2, Args1> { 
        
    Args1 operator()(const Args1& x, const Args2&) const { 
         return x;}
};

template<class Args1, class Args2>
struct project2nd : public binary_function<Args1, Args2, Args2> { 
        
    Args2 operator()(const Args1&, const Args2& y) const { 
         return y;}
};

4.3 常用仿函数

头文件为:functional

仿函数 作用
negate<>() - p
plus<>() p1 + p2
minus<>() p1 - p2
multiplies<>() p1 * p2
divides<>() p1 / p2
modulus<>() p1 % p2
equal_to<>() p1 == p2
no_equal_to<>() p1 != p2
less<>() p1 < p2
greater<>() p1 > p2
less_equal<>() p1 <= p2
greater_equal<>() p1>=p2
logical_not<>() !p
logical_and<>() p1 && p2
logical_or<>() p1 || p2
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章