杜邦接口还有一个跟他相反的叫什么_C++|一个小实例理解STL六大部件

STL主要包含容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters,或叫适配器)、算法(algorithms)、仿函数(functors,或叫函数对象)等六大部件,相互关连构成一个整体:

d8b8bff5215b0960692713c59a7122eb.png

我们知道,数组也是一个容器,但它的缺陷就是类型不是泛型,不能动态增长容量,STL的容器就是用来解决此类问题。通过模板来支持泛型,通过allocator(也是模板)来支持动态增长容量,通过迭代器(用类封装指针的模板类,实现了诸如运算符:*、->、++、--、+n、-n的重载来实现指针的移动)来容器和算法,由此实现算法作用在容器上的泛化。

以下是一个有使用到STL六大部件的小实例:

baa085804bd1497fc4db66b9db689519.png

vector > vi(ia,ia+6);

vector是一种容器类型。

int是容器内元素的类型。

allocator是指定的分配器类型,其也是一种模板,需要指定类型,这里指定int。容器构造函数有提供默认的分配器,所以也可以写为:

vector vi(ia,ia+6);

模板类的构造函数有重载,可以使用数组的元素做为vector容器的元素。

适配器在STL中扮演着转换器的角色,本质上是一种设计模式,用于将一种接口转换成另一种接口(或者说连接不同的接口),从而是原本不兼容的接口能够很好地一起运作。比如我们有一个接口 void fun(CString a) , 只接受字符串类型变量, 但是提供的数据又只有一个整型变量int a, 这时就需要一个适配器来把 int a 转换 CString a;

适配器不提供迭代器。

根据目标接口的类型,适配器可分为以下几类:

(1) 改变容器的接口,称为容器适配器;
(2) 改变迭代器的接口,称为迭代器适配器;
(3) 改变仿函数的接口,称为仿函数适配器。

STL提供了序列式容器,同时针对序列式容器提供了应用于不同场景的容器适配器,通俗讲容器适配器就是以序列式容器为底层数据结构,进一步封装了的为适应场景应用的容器。STL中提供了三种适配器,分别为stack,queue和priority_queue。

函数对象的适配器,用于特化和扩展一元或者二元函数对象,主要分为两类:

绑定器(binder):给二元函数对象绑定一个常量,转化成一元函数对象。包括bind1st和bind2nd。

取反器(negator):将谓词函数对象结果取反。包括not1和not2。


对于迭代器适配器,如输入流和输出流都不支持迭代器,而STL算法都是通过操作迭代器来实现的,如果需要用STL算法处理流中输入的数据时,就用std::istream_iterator,这就是一个适配器,它提供输入迭代器的接口,使用istream来实现。迭代器适配器包括

三种reverse(逆向)适配器,如rbegin(),rend()等。

insert迭代器,带有一个容器参数,有back_inserter(容器)、front_inserter(容器)、inserter(容器,位置)。

stream适配器:如ostream_iterator,istream_iterator。

bind1st和bind2nd函数用于将一个二元函数对象(binary functor,bf)转换成一元函数对象(unary functor,uf)。为了达到这个目的,它们需要两个参数:要转换的bf和一个值(v)。

我们在做比较的时候所写的表达式像 x > k ,x < k,这里的k是一个参数,表示你程序里面的表达式要和k值去比较。bind2nd简单的理解就是把k作为比较表达式的第二个参数。如果使用bind1st则对应的表达式是 k > x,k < x,也就是把k作为比较表达式的第一个参数。

f = std::bind1st( functor, v); 'f( x)'等价于'functor( v, x)'

f = std::bind2nd( functor, v); 'f( x)'等价于'functor( x, v)'

bind1st和bind2nd例子:

int a[] = {1, 2, 100, 200};std::vector< int> arr(a, a + 4);// 移除所有小于100的元素arr.erase( std::remove_if( arr.begin(), arr.end(),std::bind2nd( std::less< int>(), 100)), arr.end());

这里的比较表达式相当于arr.value < 100。

如果用bind1st则表达的意思就恰恰相反:

// 移除所有大于100的元素arr.erase( std::remove_if( arr.begin(), arr.end(),std::bind1st( std::less< int>(), 100)), arr.end());

这里的表达式相当于100 < arr.value。

为了实现删除大于100的元素你同样可以使用bind2nd:

// 移除所有大于100的元素arr.erase( std::remove_if( arr.begin(), arr.end(),std::bind2nd( std::greater< int>(), 100)), arr.end());

x <= k怎么实现呢,std又提供了一个好东西not1,我们可以说 !(x > k) 和 x <= k是等价的,那么我们看看下面的表达式:

// 移除所有小于等于100的元素arr.erase( std::remove_if( arr.begin(), arr.end(),std::not1(std::bind2nd( std::greater< int>(), 100))), arr.end());

not1是构造一个与谓词结果相反的一元函数对象,not2是构造一个与谓词结果相反的二元函数对象。

int a[] = {1, 2, 100, 200};std::vector< int> arr(a, a + 4);// 移除所有小于100的元素arr.erase( std::remove_if( arr.begin(), arr.end(), std::bind2nd( std::less< int>(), 100)), arr.end());这里的比较表达式相当于arr.value < 100如果用bind1st则表达的意思就恰恰相反// 移除所有大于100的元素arr.erase( std::remove_if( arr.begin(), arr.end(), std::bind1st( std::less< int>(), 100)), arr.end());这里的表达式相当于100 < arr.value当然为了实现删除大于100的元素你同样可以使用bind2nd// 移除所有大于100的元素arr.erase( std::remove_if( arr.begin(), arr.end(), std::bind2nd( std::greater< int>(), 100)), arr.end());前面说道=的比较,比如说x <= k怎么实现呢,std又提供了一个好东西not1,我们可以说 !(x > k) 和 x <= k是等价的,那么我们看看下面的表达式:// 移除所有小于等于100的元素arr.erase( std::remove_if( arr.begin(), arr.end(), std::not1(std::bind2nd( std::greater< int>(), 100))), arr.end());说明:not1是否定返回值是单目的函数,std中还有not2它是否定返回值是双目的函数。

not2 example:

// not2 example#include  // std::cout#include  // std::not2, std::equal_to#include  // std::mismatch#include  // std::pairint main () { int foo[] = {10,20,30,40,50}; int bar[] = {0,15,30,45,60}; std::pair firstmatch,firstmismatch; firstmismatch = std::mismatch (foo, foo+5, bar, std::equal_to()); firstmatch = std::mismatch (foo, foo+5, bar, std::not2(std::equal_to())); std::cout << "First mismatch in bar is " << *firstmismatch.second << ''; std::cout << "First match in bar is " << *firstmatch.second << ''; return 0;}/* outputFirst mismatch in bar is 0First match in bar is 30*/

附小实例代码:

#include #include #include #include using namespace std;int main(){int ia[7] = {26,210,12,47,109,83};vector > vi(ia,ia+6);// 分配器也是一个模板,需要告诉它每次分配的是什么东西cout<(),40)));// 统计小于40的否定的元素数量return 0;}

视频:

[侯捷]C++ STL 体系结构与内核分析

https://www.bilibili.com/video/av45108908?p=2

-End-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值