C++仿函数

时间:2020-05-16
本文章向大家介绍C++仿函数,主要包括C++仿函数使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

C++的标准库STL里面有6大部件,其中之一为仿函数。初始看到这一名字可能让人摸不着头脑:函数倒是挺容易理解,何故又起个仿函数的名字呢?本文将带你揭开它看起来挺让人迷惑但是实际上很简单的面纱。

仿函数,看名字就知道它肯定和函数有什么关联,但是也肯定和函数有什么区别。函数主要是一块接收输入参数然后按照一定逻辑组织起来计算输出参数的过程(这里把print之类的也称为输出参数,只不过是输出到屏幕上或者文件中),简而言之就是一个执行特定功能的代码块。仿函数也是执行特定功能的代码块,但是与函数不同的是,仿函数写的形式看起来有一些不一样。下面看一个简单例子:

1 template<T>
2 struct plus{
3     T operator()(const T&x,const T& y){
4         return x+y;
5     }
6 }

这段代码的主要功能是实现一个加的功能,从名字也可以轻易地看出来。从代码的具体结构看,仿函数写了一个类,这个类的名字叫plus,类中仅有一个operator()的实现。目前为止仿函数看起来虽然挺简单,但是好像没啥用啊!!官人别急,马上就上菜了。

介绍仿函数的用途之前,有必要介绍一下无名对象。

在C++中无名对象是非常常见的,不过很多时候我们并不会注意到它的存在,例如下面一个例子:

int len(std::string str){
    return str.size();
}

当我们在参数传递时,编译器实际上做的事是拷贝调用的时候传递的参数一份,然后利用拷贝的数据进行操作,这里就会涉及到无名对象(实际上一个无名的string,我们不妨利用一下python的思想,把所有东西都看成是对象),根据以上的说法,上面这以函数与一下的函数使用有不同之处:

1 int len(std::string& str){
2     return str.size();
3 }

这里我们仅仅是加了一个按引用传递的符号,这时再调用len(str),过程就应该不一样了。如果各位看官想要测试,可以重写一下new方法:

1 void* operator new(size_t size){
2     std::cout<<"Allocating: "<<" bytes"<<std::endl;
3     return malloc(size);
4 }

这时一旦有new方法被调用,则我们就可以看到输出信息,说明进行了内存的申请操作,具体测试请各位大爷自行测试。

事实上,C++17标准增加了一个string_view类,可以使用此类达到一些特定的string的参数传递作用,例如我们只是想要比较一下字符串中部分字符,那么使用string_view是不错的选择,再如我们都知道再使用vector容器时,可以使用.push_back()方法追加元素,也有一个非常类似的方法:.emplace_back();实现的功能也是追加元素,不同之处在于push_back会创建一个无名对象但是emplace_back不会,具体测试也请各位大爷利用上面写的new方法进行测试。

啰嗦了一大堆,无名对象跟仿函数有什么卵关系呢?

实际上仿函数最常用的也是无名对象的形式,举个例子,再algorithm头文件中,有一个经常用到的方法叫做sort,该方法默认功能是给指定容器的元素按照从小到大的顺序排序,那么问题来了,如果我们想要从大到小排序呢?或者对于矩阵我们想要不按第一列,而是按照某一列排序呢?这时仿函数就可以发挥作用了。对于上述的问题,通常程序大爷的解决方法是写一个lamda函数(不知道的大爷喝口雪碧)或者自己写一下cmp方法作为sort函数的第三个参数,实际上这一cmp方法也可以用仿函数试现。

以上拿sort方法举例了,实际上,其他方法也完全可以使用,或者我们再写东西的时候,也可以写自己的仿函数。下面举一个纯粹使用仿函数的例子:

1 int mian(){
2     plus<int> p;
3     std::cout<<p(2,3)<<std::endl;
4     std::cout<<plus<int>(2,3)<<std::endl;
5 }

讲到这里应该比较清楚了吧各位大爷?

原文地址:https://www.cnblogs.com/thugf/p/12898860.html