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

STL适配器包括迭代器适配器(如back_insert_iterator、front_insert_iterator等)、容器适配器(如stack、queue、priority_queue)和函数适配器(如bind、mem_fn)。它们用于转换迭代器行为、调整容器功能和修改函数参数及调用方式,提高代码复用性和灵活性。例如,bind可以绑定函数参数,mem_fn能将成员函数转换为可调用对象。

目录

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; // 输出8
    return 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值