[C++ Primer] 泛型算法
泛型算法
初识泛型
-
大多数算法定义在头文件algorithm中。标准库还在头文件numeric中定义了一组数值范型算法。
-
那些只接受一个单一迭代器来表示第二个序列的算法,都假定第二个序列至少与第一个序列一样长。
// v2中的元素数目应该至少与v1一样多 equal(v1.cbegin(), v1.cend(), v2.cbegin())
-
标准库算法对迭代器而不是容器进行操作,因此,算法不能(直接)添加或删除元素。
定制操作
-
可调用对象: 对于一个对象或一个表达式,如果可以对其使用调用运算符,则称它为可调用的。即,如果e是一个可调用的表达式,则我们可以编写代码
e(args)
,其中args是一个逗号分隔的一个或多个参数的列表。可调用对象主要有函数和函数指针、重载函数调用运算符的类、以及lambda表达式。
lambda表达式
一个lambda表达式表示一个可调用的代码单元,可以将其理解为一个未命名的内联函数。与任何函数类似,一个lambda具有一个返回类型、一个参数列表和一个函数体。但与函数不同,lambda可能定义在函数内部。具有如下形式:
[capture list](parameter list) -> return type { function body }
capture list lambda所在函数中定义的局部变量的列表
可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体
auto f = [] { return 32};
此例中,定义了一个可调用对象f,不接受参数,返回42。 lambda的调用方式与普通函数的调用方式相同,都是使用调用运算符:
cout << f() << endl; // 打印42
一个lambda只有在其捕获列表中捕获一个它所在函数中的局部变量,才能在函数体中使用该变量。
当以引用方式捕获一个变量时,必须保证在lambda执行时变量是存在的。
-
默认情况下,如果一个lambda体包含return之外的任何语句,则编译器假定此lambda返回void。
-
标准库bind函数
✏✏✏
再探迭代器
-
标准库在头文件iterator还定义了额外的几种迭代器:
- 插入迭代器: 被绑定到一个容器上,可用来向容器插入元素,
- 流迭代器: 被绑定到输入或输出流上,可用来遍历所关联的IO流。
- 反向迭代器: 迭代器向后面移动而不是向前移动,除了forward_list之外的标准库容器都有反向迭代器。
- 移动迭代器:这些迭代器移动元素,而不是拷贝元素。
-
插入迭代器
有三种类型,差异在于元素插入的位置:
- back_inserter 创建一个使用push_back的迭代器。
- front_inserter 创建一个使用push_front的迭代器。
- inserter 创建一个使用insert的迭代器。
-
iostream迭代器
istream_iterator 要读取的类型必须定义了输入运算符>>,与读取数据流绑定,常见操作如下:
ostream_iterator 可以对任何具有输出运算符(<<运算符)的类型定义,当创建一个ostream_iterator迭代器时,可以提供(可选)第二参数,它是一个字符串,在输出每个元素后都会打印此字符串。此字符串必须是一个C风格字符串(即,一个字符串字面常量或一个指向以空字符结尾的字符数组的指针)。必须将ostream_iterator绑定到一个指定的流,不允许空的或表示尾后位置的ostream_iterator。

可以为任何定义了输入运算符(>>)的类型创建istream_iterator对象,同样的,只要类型有输出运算符(<<),就可以为其定义ostream_iterator。
-
反向迭代器
泛型算法结构
-
算法所要求的迭代器操作可以分为5个迭代器类别。
-
对于list和forward_list,应该优先使用成员函数版本的算法而不是通用算法。
-
splice成员,链表类型定义了splice算法,此算法是链表数据结构所特有的。
-
链表特有的操作会改变容器。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗