STL --- 七. 适配器(Adapters)

news/2024/10/18 2:33:21/

目录

1、STL适配器介绍和分类

2、迭代器适配器

3、容器适配器

4、函数适配器


1、STL适配器介绍和分类

STL适配器是一种将一个容器(或其他数据结构)转换为另一种容器(或数据结构)的功能。

它们是一种高效的工具,用于将现有的代码与STL容器一起使用,同时也允许开发人员根据需要进行自定义。

(1)迭代器适配器:将迭代器转换为另一种类型的迭代器,例如反向迭代器。

(2)容器适配器:将一种容器类型转换为另一种容器类型,例如将栈转换为队列。

(3)函数适配器:将一个函数转换为另一种函数,例如使用bind()函数将一个参数绑定到函数中。

STL适配器提供了一种方便的方法来重用现有的代码,并且可以大大减少开发时间和代码量。

2、迭代器适配器

STL迭代器适配器是指一些函数和类,它们可以将一个迭代器转换成另一个迭代器,或者修改一个迭代器的行为。这些适配器可以帮助我们更方便地使用STL中的算法和容器。

常见的STL迭代器适配器包括:

(1)back_insert_iterator:将元素插入容器的末尾。

(2)front_insert_iterator:将元素插入容器的开头。

(3)insert_iterator:将元素插入容器的任意位置。

(4)reverse_iterator:将迭代器的遍历顺序反转。

(5)istream_iterator:从输入流中读取元素。

(6)ostream_iterator:将元素输出到输出流中。

使用这些迭代器适配器,我们可以更方便地实现一些常见的操作,比如将元素插入到容器中、遍历容器的逆序、从文件中读取数据等。

迭代器的一些示例:

(1)back_inserter是一个适配器,可以将一个迭代器转换为一个插入器迭代器。它可以将元素添加到容器的末尾:

std::vector<int> v1 {1, 2, 3};
std::vector<int> v2;
std::copy(v1.begin(), v1.end(), std::back_inserter(v2));

在上面的示例中,back_inserter(v2)将返回一个插入器迭代器,该迭代器可以将元素添加到v2的末尾。使用std::copy算法将v1的元素复制到v2时,back_inserter(v2)将确保将元素添加到v2的末尾。

(2)front_inserter是一个适配器,可以将一个迭代器转换为一个插入器迭代器。它可以将元素添加到容器的开头:

std::vector<int> v1 {1, 2, 3};
std::vector<int> v2;
std::copy(v1.begin(), v1.end(), std::front_inserter(v2));

在上面的示例中,front_inserter(v2)将返回一个插入器迭代器,该迭代器可以将元素添加到v2的开头。使用std::copy算法将v1的元素复制到v2时,front_inserter(v2)将确保将元素添加到v2的开头。

(3)inserter是一个适配器,可以将一个迭代器转换为一个插入器迭代器。它可以将元素添加到容器的任意位置:

std::vector<int> v1 {1, 2, 3};
std::vector<int> v2 {4, 5, 6};
std::copy(v1.begin(), v1.end(), std::inserter(v2, v2.begin()+1));

在上面的示例中,inserter(v2, v2.begin()+1)将返回一个插入器迭代器,该迭代器可以将元素添加到v2的第2个位置(v2.begin()+1)。使用std::copy算法将v1的元素复制到v2时,inserter(v2, v2.begin()+1)将确保将元素添加到v2的第2个位置。

3、容器适配器

STL(标准模板库)提供了多种容器适配器,用于提供不同的容器类的接口和实现。以下是常见的容器适配器:

(1)stack(栈):基于 deque(双端队列)实现,提供了栈的接口,即后进先出(LIFO)的数据结构。

(2)queue(队列):基于 deque(双端队列)实现,提供了队列的接口,即先进先出(FIFO)的数据结构。

(3)priority_queue(优先队列):基于 vector(动态数组)或 deque(双端队列)实现,提供了优先队列的接口,即按照一定的优先级顺序取出元素。

(4)bitset(位集):提供了一种高效的方式来存储和操作位序列,可以用于位运算和布尔逻辑运算。

这些容器适配器都是基于现有的容器类实现的,因此可以根据具体的需求选择适当的容器适配器。

4、函数适配器

STL 函数适配器是一种能够修改现有函数的参数、返回值或调用方式的工具。它们将一种函数类型转换为另一种函数类型,使得可以在不改变原有函数的情况下,适应不同的需求。

STL 函数适配器有三种类型:

(1)函数指针适配器(Function Pointer Adapters):将一个函数指针转换成另一个函数指针,以适应不同的参数或返回值类型。

(2)函数对象适配器(Function Object Adapters):将一个函数对象转换成另一个函数对象,以适应不同的参数或返回值类型。

(3)迭代器适配器(Iterator Adapters):将一个迭代器转换成另一个迭代器,以适应不同的迭代方式或容器类型。

STL 函数适配器可以大大提高代码的复用性和可读性,使得我们能够更加灵活地使用现有的函数库。

STL函数适配器一些示例:

(1)bind函数适配器

bind 的基本语法如下:std::bind(func, arg1, arg2, ..., argN)其中,func 表示需要绑定的函数或函数指针,arg1, arg2, ..., argN 表示需要绑定的参数。
绑定后的函数对象可以通过调用 operator()() 方法执行。

bind函数适配器可以将一个函数的参数绑定到指定的值上,从而产生一个新的函数对象。

例如,将一个二元函数的第一个参数绑定到5,产生一个新的一元函数:

#include <iostream>
#include <functional>using namespace std;
using namespace placeholders;int add(int a, int b) {return a + b;
}int main() {auto f = bind(add, 5, _1);cout << f(3) << endl; // 输出8return 0;
}

(2)mem_fn函数适配器

mem_fn函数适配器可以将一个类成员函数转换为一个函数对象,从而可以方便地在算法中使用。

例如,将一个类成员函数传递给find_if算法:

#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>using namespace std;class Person {
public:Person(string name, int age) : name_(name), age_(age) {}bool isAdult() const {return age_ >= 18;}
private:string name_;int age_;
};int main() {vector<Person> people{{"Tom", 20}, {"Jerry", 15}, {"Alice", 25}};auto it = find_if(people.begin(), people.end(), mem_fn(&Person::isAdult));if (it != people.end()) {cout << it->isAdult() << endl; // 输出1}return 0;
}

std::find_if 是C++ STL中的一个算法,用于在容器中查找符合特定条件的元素。它接受三个参数:容器的起始和结束迭代器,以及一个谓词函数(predicate function),用于判断每个元素是否符合条件。std::find_if会从容器的起始位置开始依次遍历每个元素,直到找到符合条件的元素或遍历到容器的末尾。如果找到符合条件的元素,则返回该元素的迭代器;否则返回容器的结束迭代器。

std::mem_fn 是一个函数模板,用于创建一个可调用对象,该对象将成员函数作为其操作,并将对象作为其第一个参数。这个可调用对象可以用来调用成员函数,并可以绑定到一个对象上。

(3)not1和not2函数适配器

not1和not2函数适配器可以将一个一元或二元谓词函数取反,从而可以方便地在算法中使用。

例如,使用not1将一个判断是否为偶数的谓词函数取反:

#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>using namespace std;bool isEven(int num) {return num % 2 == 0;
}int main() {vector<int> nums{1, 2, 3, 4, 5};auto it = find_if(nums.begin(), nums.end(), not1(ptr_fun(isEven)));if (it != nums.end()) {cout << *it << endl; // 输出1}return 0;
}

(4)transform函数适配器

transform函数适配器可以将一个函数应用于一个序列中的每个元素,从而生成一个新的序列。

例如,将一个序列中的所有元素加1:

#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>using namespace std;int main() {vector<int> nums{1, 2, 3, 4, 5};vector<int> result;transform(nums.begin(), nums.end(), back_inserter(result), bind(plus<int>(), _1, 1));for (auto num : result) {cout << num << " "; // 输出2 3 4 5 6}cout << endl;return 0;
}


http://www.ppmy.cn/news/104007.html

相关文章

R语言生物群落(生态)数据统计分析与绘图(从数据整理到分析结果展示)

R 语言作的开源、自由、免费等特点使其广泛应用于生物群落数据统计分析。生物群落数据多样而复杂&#xff0c;涉及众多统计分析方法。以生物群落数据分析中的最常用的统计方法回归和混合效应模型、多元统计分析技术及结构方程等数量分析方法为主线&#xff0c;通过多个来自经典…

注意:腾讯云轻量应用服务器十大限制说明

腾讯云轻量应用服务器相对于云服务器CVM是有一些限制的&#xff0c;比如轻量服务器不支持更换内网IP地址&#xff0c;不支持自定义私有网络VPC&#xff0c;内网连通性方面也有限制&#xff0c;轻量不支持CPU内存、带宽或系统盘单独升级&#xff0c;只能整个套餐整体升级&#x…

SpringBoot 配置文件和日志文件

目录 一、SpringBoot配置文件 配置文件的格式 .properties配置文件格式 .yml配置文件格式 .properties 与 .yml的区别 配置文件的读取 .properties 与 .yml的区别 设置不同环境的配置⽂件 二、SpringBoot日志文件 日志打印的步骤 得到日志对象 方法一&#xff1a;使…

R实践——【rgplates】安装、介绍、入门

【rgplates】安装、介绍、入门 1. rgplates 安装1.1 easy way1.2 备案方法 2. rgplates 介绍3. rgplates 在线方法入门3.1 加载rgplates3.2 板块重建3.3 独立的地点坐标3.3.1 单个现存坐标点3.3.2 单个点的古坐标3.3.3 多个点的古坐标 3.4 现今的海岸线3.5 其他的重建模型3.6 在…

2023年,软件测试怎么样?

​2022年因为各种不可抗力原因&#xff0c;大厂裁员&#xff0c;失业等等频频受到关注。 不解释&#xff0c;确实存在&#xff0c;各行各业都很难&#xff0c;但是&#xff0c;说软件测试行业不吃香&#xff0c;我还真不认同&#xff08;不是为培训机构说好话&#xff0c;大环…

Linux 安装nodejs、npm、yarn、nrm(超实用)

前言&#xff1a;初衷想要本地通过dockerfile文件直接把项目打包到linux服务器&#xff0c;不用再本地加载再上传等&#xff0c;后续再贴上配置文件 一、什么是nodejs 来自官网的介绍&#xff0c;Node.js 是一个开源的跨平台 JavaScript 运行时环境。它几乎是任何类型项目的流…

Groovy学习笔记-2.Groovy相关基础信息

更多代码相关的内容可以参考&#xff1a;https://github.com/zclhit/groovy_learning/tree/main 代码结构 注释 #!注释&#xff0c;只允许出现在groovy脚本的第一行&#xff0c;通过这种注释可以方便Unix shell进行定位启动并运行 //单行注释 /* xxxxx */多行注释 /** xxxxx…

基于复旦微FMQL45T900 全国产ARM+FPGA核心板方案

XM745D 是一款基于上海复旦微电子 FMQL45T900 的全国产化 ARM 核心板。该核心板将复旦微的 FMQL45T900&#xff08;与 XILINX 的 XC7Z045-2FFG900I 兼容&#xff09;的最小系统集成在了一个 87*117mm 的 核心板上&#xff0c;可以作为一个核心模块&#xff0c;进行功能性扩展&a…