在C++的学习过程中经常会提到适配器的概念,简单记录自己的理解:
1.适配器的意思就是将某些已经存在的东西进行限制或者组合变成一个新的东西,这个新的东西体现一些新的特性,但底层都是由一些已经存在的东西实现的。
2.我看到的C++中有容器适配器,迭代器适配器和函数适配器。
3.容器适配器就是stack和queue和priority_queue。有些时候我们直接将这几个归纳为容器的一种。但是实际上他们是容器适配器,就比如栈的前进后出的特性,我们完全自己利用vector容器写出来。
同样在C++中stack和queue的底层默认是通过deque容器来实现的,priority_queue底层默认是通过vector容器来实现的。并且允许我们更换其他符合要求的容器作为底层实现。
所以容器适配器在我看来只是一种思想,概念而已,真正使用这些容器适配器的时候完全可以将其作为容器一样使用。
4.迭代器适配器。同上面的容器迭代器的思想用法一样,至于我们平时使用的迭代器中哪些是基础迭代器哪些是迭代器适配器,想要了解的可以自行查找资料,但大多数情况下我们只要知道有这个概念就行了,真正使用过程中并不需要分得这么清楚。
5.函数适配器:
先看下面一个例子,find_count是标准库中的一个算法,用来找出容器中满足条件的元素的个数。如找出容器vec中大于x的数的个数。
使用lambda表达式写法:
std::vector<int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9};
int x = 5;
int count = std::count_if(vec.begin(), vec.end(), [x](int val) {
return val > x;
});
cout << count << endl;
这里如果我们要通过自己声明一个函数作为传入参数的时候,我们写这个函数的时候就会遇到一个问题就是我们要将局部变量x传入外面定义的这个函数中,而外面定义的这个函数只能接收一个传入参数,因为count_if的参数函数模板只能有一个传入参数。在lambda中可以在捕获列表[]中传入局部变量在lambda函数内部使用。
这里就需要用到一个叫bind的函数,这个函数可以对一个函数进行修饰返回一个修饰后的函数,这个返回的函数就叫做函数适配器。也就是底层是一个已经存在的函数,通过对这个函数的修改(改变参数个数和顺序,添加新的参数等)变成的新的函数。
#include <algorithm>
#include <functional>
using std::cout;
using std::endl;
bool isGreaterX(int val,int x){
return val > x;
}
int main(int argc, char *argv[])
{
std::vector<int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9};
int x = 5;
auto isGreaterX1 = std::bind(isGreaterX,std::placeholders::_1,x);
int count = std::count_if(vec.begin(), vec.end(), isGreaterX1);
cout << count << endl;
}
这里std::bind(isGreaterX,std::placeholders::_1,x)返回的isGreaterX1 函数只有一个int类型的传入参数,将这个传入参数作为sGreaterX的第一个参数(因为std::placeholders::_1的位置在第一个参数),将x做为isGreaterX的第二个参数再去调用isGreaterX。