深入探究C++中的仿函数和迭代器——提升你的STL技能

简介: 作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段>——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程,会持续分享学习成果和小项目的作者主页:热爱编程的小K专栏链接:c++欢迎各位→点赞 + 收藏 + 留言​总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 ————————————————版权声明:本文为CSDN博主「热爱编程的小K」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_72157449

文章目录

一、仿函数

1、介绍

2、为什么要有仿函数?

3、核心

A、仿函数的调用

B、应用

C、标准库仿函数

4、仿函数优点

5、仿函数作用

二、迭代器

1、分类

2、辅助函数

3、流型迭代器

一、仿函数

1、介绍

仿函数(Functor)又称为函数对象(Function Object)是一个能行使函数功能的类,仿函数是定义了一个含有operator()成员函数的对象,可以视为一个一般的函数,只不过这个函数功能是在一个类中的运算符operator()中实现,是一个函数对象,它将函数作为参数传递的方式来使用。


写一个简单类,除了维护类的基本成员函数外,只需要重载 operator() 运算符 。这样既可以免去对一些公共变量的维护,也可以使重复使用的代码独立出来,以便下次复用。


STL 中也大量涉及到仿函数,有时仿函数的使用是为了函数拥有类的性质,以达到安全传递函数指针、依据函数生成对象、甚至是让函数之间有继承关系、对函数进行运算和操作的效果。比如 STL 中的容器 set 就使用了仿函数 less ,而 less 继承的 binary_function,就可以看作是对于一类函数的总体声明,这是函数做不到的。


2、为什么要有仿函数?

1,假如客户有一个需求摆在我们的面前,编写一个函数:函数可以获得斐波拉契数列每项的值;每调用一次便返回一个值;函数可根据需要重复使用。我们之前在 C 语言中也讲过斐波拉契数列,相信这个很好实现了。那么我们就编写的程序如下

微信截图_20230425195329.png

我们就开心的完成任务了,于是交给客户了。过两天,客户又给打回来了。说是存在几个问题:函数一但调用就无法重来,静态局部变量处于函数内部,外界无法改变。函数为全局函数,是唯一的,无法多次独立使用。无法指定某个具体的数列项作为初始值。于是我们想着将静态局部变量改为去全局变量,再次重新调用时,便将全局变量重新初始化,重新如下

微信截图_20230425195544.png

微信截图_20230425200553.png

是满足这个需求了,但是要在使用时需要重新初始化全局变量,客户肯定不干啊。所以这个解决方案不可行。于是乎,我们在 C++ 中一个吊炸天的技术来了:函数对象。


先来说说函数对象:


使用具体的类对象取代函数;

该类的对象具备函数调用的行为;

构造函数指定具体数列项的起始位置;

多个对象相互独立的求解数列项。

微信截图_20230425200718.png

下来我们来看看最终的解决方案

微信截图_20230425200856.png

微信截图_20230425200941.png

我们看到已经实现了所有需求,并且随时想从哪个数开始都行。

2,比如,有一个简单需求:统计一个vector中,元素等于3的数量。解决方法可能会是:

微信截图_20230425201059.png

其实,统计容器中某个元素的数量,C++中有一个函数count

微信截图_20230425201151.png

对于上面的统计元素个数没有拓展性。比如:统计v中元素大于于3的元素个数呢?为此我们必须再设计一个greater_count函数:

微信截图_20230425201214.png
这样写就很麻烦,我只需要改变一下规则,就需要多一个函数,咱们可以把里面的比较规则,写成一个函数(可调用的对象),通过传参实现比较。

微信截图_20230425201431.png微信截图_20230425201503.png

这样是不是就轻松很多了,但是这里的统计元素3,我们要通过count_if传到比较函数里面去,非常的丑陋对不对。有一种写法,可以不通过参数传进去。

首先,删掉count_if中的最后一个参数val。

然后,把equal和great稍加修改一下。

微信截图_20230425201650.png微信截图_20230425201707.png或者使用lambda表达式

微信截图_20230425201759.png

其实lamda表达式出现之后(C++11),仿函数(C++98)的作用已经被削弱了,使用lamda会让我们使用STL方便许多。

对于count_if 里有和我们写的一模一样的函数,以后直接使用即可

那么使用仿函数,怎么实现上述功能呢?

微信截图_20230425201905.png微信截图_20230425201922.png

可以继续升级~

微信截图_20230425202021.png微信截图_20230425202043.png
3、核心

仿函数是让类名模仿函数调用的行为---->函数名(参数) ,让类名能够 : 类名(参数) 方式使用


自己写仿函数关键点在于重载()运算符,所谓的模仿函数的行为,本质先构造一个无名对象,然后通过对象隐式调用重载函数


自己写仿函数

标准库中的仿函数(不需要记,自己会写了,自己创造)

仿函数一般有两个作用:


充当比较准则

充当算法或者容器构建的参数

A、仿函数的调用

必须加上{},要不然解析不了,分不清楚是构造函数还是啥

sum{}(2, 3)

微信截图_20230425202206.png

B、应用

冒泡排序函数准则的写入,使用结构体和类分别进行书写,方便理解

微信截图_20230425202253.png

微信截图_20230425202328.png

C、标准库仿函数

我的评价是不用记,用到的时候自己写一个或者查一下,标准库的太多了,还比较难记

微信截图_20230425202458.png

微信截图_20230425202533.png

4、仿函数优点

如果可以用仿函数实现,那么你应该用仿函数,而不要用CallBack(CallBack技术是一种编程技术,它允许将一个函数作为参数传递给另一个函数,以便在需要时执行该函数。这种技术通常用于事件处理程序和异步编程中。)。原因在于:


仿函数可以不带痕迹地传递上下文参数。而CallBack技术通常使用一个额外的void*参数传递。这也是多数人认为CallBack技术丑陋的原因。


仿函数技术可以获得更好的性能,这点直观来讲比较难以理解。


5、仿函数作用

仿函数通常有下面四个作用:


作为排序规则,在一些特殊情况下排序是不能直接使用运算符<或者>时,可以使用仿函数。

作为判别式使用,即返回值为bool类型。

同时拥有多种内部状态,比如返回一个值得同时并累加。

作为算法for_each的返回值使用。

二、迭代器

1、分类

迭代器是一个类中类,让类中类对象模仿指针的行为,迭代器通常是用来访问容器的

微信截图_20230425202739.png按照功能上来说分为三类:


  • 正向迭代器
  • 双向迭代器:list set map
  • 随机访问迭代器: array,vector,deque

注意点: stack与queue以及priority_queue 不支持迭代器访问

微信截图_20230425202859.png

微信截图_20230425202936.png

2、辅助函数


  • advance(iter,n):移动
  • distance(beginPos ,endPos): 元素个数
  • iter_swap(first,second):交换

微信截图_20230425203102.png

微信截图_20230425203154.png

3、流型迭代器

输出流型迭代器


ostream_iterator object(ostream& out);

ostream_iterator object(ostream& out,const char* str);

object=value : 等效 cout<

输入流型迭代器istream_iterator object; //End-of-stream


istream_iterator object(istream& in);

*object 等效 cin操作

微信截图_20230425203522.png微信截图_20230425203537.png

原文链接:https://blog.csdn.net/qq_72157449/article/details/130333820


相关文章
|
1天前
|
设计模式 存储 C++
【C++/STL】:stack/queue的使用及底层剖析&&双端队列&&容器适配器
【C++/STL】:stack/queue的使用及底层剖析&&双端队列&&容器适配器
19 2
|
2天前
|
C++ 容器
C++ STL:各类容器的特点和优缺点比较
C++ STL:各类容器的特点、优势、劣势比较
|
1天前
|
编译器 C++ 容器
【C++/STL】:list容器的深度剖析及模拟实现
【C++/STL】:list容器的深度剖析及模拟实现
8 2
|
1天前
|
存储 C++ 容器
【C++/STL】:list容器的基本使用
【C++/STL】:list容器的基本使用
6 1
|
1天前
|
存储 算法 C++
【C++/STL】:vector容器的基本使用
【C++/STL】:vector容器的基本使用
12 1
|
4天前
|
算法 数据处理 C++
C++一分钟之-迭代器与算法
【6月更文挑战第21天】C++ STL的迭代器统一了容器元素访问,分为多种类型,如输入、输出、前向、双向和随机访问。迭代器使用时需留意失效和类型匹配。STL算法如查找、排序、复制要求特定类型的迭代器,注意容器兼容性和返回值处理。适配器和算法组合增强灵活性,但过度使用可能降低代码可读性。掌握迭代器和算法能提升编程效率和代码质量。
22 3
|
4天前
|
存储 算法 C++
C++一分钟之-标准模板库(STL)简介
【6月更文挑战第21天】C++ STL是高效通用的算法和数据结构集,简化编程任务。核心包括容器(如vector、list)、迭代器、算法(如sort、find)和适配器。常见问题涉及内存泄漏、迭代器失效、效率和算法误用。通过示例展示了如何排序、遍历和查找元素。掌握STL能提升效率,学习过程需注意常见陷阱。
21 4
|
9天前
|
算法 前端开发 Linux
【常用技巧】C++ STL容器操作:6种常用场景算法
STL在Linux C++中使用的非常普遍,掌握并合适的使用各种容器至关重要!
33 10
|
2天前
|
存储 安全 算法
C++的内置数组和STL array、STL vector
C++的内置数组和STL array、STL vector
|
6天前
|
存储 编译器 C++