目录
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;
}