5.1 c++ STL 容器适配器简介

1. 适配器简介

在详解什么是容器适配器之前,初学者首先要理解适配器的含义。

其实,容器适配器中的“适配器”,和生活中常见的电源适配器中“适配器”的含义非常接近。我们知道,无论是电脑、手机还是其它电器,充电时都无法直接使用 220V 的交流电,为了方便用户使用,各个电器厂商都会提供一个适用于自己产品的电源线,它可以将 220V 的交流电转换成适合电器使用的低压直流电。

从用户的角度看,电源线扮演的角色就是将原本不适用的交流电变得适用,因此其又被称为电源适配器。

2. 容器适配器

简单理解 容器适配器, 就是将不适用的序列式容器 (包括vector, deque, list ) 变得适用

即通过封装某个序列式容器,并重新组合该容器中包含的成员函数, 使其满足某些特定场景的需要;

2.1 适配器举例

举一个例子,假设一个代码模块 A,它的构成如下所示:


class A{
public:
    void f1(){}
    void f2(){}
    void f3(){}
    void f4(){}
};

现在我们需要设计一个模板 B,但发现,其实只需要组合一下模块 A 中的 f1()、f2()、f3(),就可以实现模板 B 需要的功能。其中 f1() 单独使用即可,而 f2() 和 f3() 需要组合起来使用,如下所示:

class B{
private:
    A * a;
public:
    void g1(){
        a->f1();
    }
    void g2(){
        a->f2();
        a->f3();
    }
};


可以看到,就如同是电源适配器将不适用的交流电变得适用一样,

模板 B 将不适合直接拿来用的模板 A 变得适用了,因此我们可以将模板 B 称为 B 适配器。

容器适配器的底层实现和模板 A、B 的关系是完全相同的。

2.2 容器适配器的本质

容器适配器本质上还是容器,只不过此容器模板类的实现,利用了大量其它基础容器模板类中已经写好的成员函数。当然,如果必要的话,容器适配器中也可以自创新的成员函数。

注意, STL 中的容器适配器, 其内部使用的基础容器并不是固定的, 用户可以在满足特定条件的多个基础容器中根据需求 选择;

3. 容器适配器的分类

  1. stack 栈适配器
  2. queue 队列适配器;
  3. priority_queue 优先权队列适配器;

各个容器适配器,所使用的默认基础容器, 以及可以供用户选择的基础容器, 如表所示

表 1 STL 容器适配器及其基础容器

容器适配器 基础容器筛选条件 默认使用的基础容器
stack 基础容器需包含以下成员函数: empty() , size() ,back(), push_back(), pop_back()满足条件的基础容器有 vector、deque、list。 deque
queue 基础容器需包含以下成员函数:empty(),size(),front(),back() ,push_back(), pop_front()满足条件的基础容器有 deque、list。 deque
priority_queue 基础容器需包含以下成员函数:empty(),size(),front(),push_back(),pop_back(), 满足条件的基础容器有vector、deque。 vector

不同场景下, 不同的序列式容器其底层采用的数据结构不同
因此,容器适配器的执行效率也不尽相同;

4. 小结

由以上知识点,

  1. C++中stack 是容器么?
  2. 我们使用的stack是属于哪个版本的STL?
  3. 我们使用的STL中stack是如何实现的?
  4. stack 提供迭代器来遍历stack空间么?

4.1 stack 是容器适配器

stack 是容器适配器,虽然本质上是容器,但其机理是调用底层的基础容器, 进行改动然后封装成特定功能的容器;

4.2 stack 属于哪个版本的STL?

通常情况下,我们使用的是 SGI STL 数据结构中的 stack ;

三个最为普遍的STL版本:

  • HP STL 其他版本的C++ STL,一般是以HP STL为蓝本实现出来的,HP STL是C++ STL的第一个实现版本,而且开放源代码。

  • P.J.Plauger STL 由P.J.Plauger参照HP STL实现出来的,被Visual C++编译器所采用,不是开源的。

  • SGI STL 由Silicon Graphics Computer Systems公司参照HP STL实现,被Linux的C++编译器GCC所采用,SGI STL是开源软件,源码可读性甚高。

接下来介绍的栈和队列也是SGI STL里面的数据结构, 知道了使用版本,才知道对应的底层实现。

5.1 c++ STL 容器适配器简介_第1张图片

4.3 我们使用的STL中stack是如何实现的?

栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器可以 是vector,deque,list ,也就是说我们可以控制使用哪种容器来实现栈的功能。

所以STL中栈被归类为container adapter(容器适配器)。

而 vector, deque, list 的底层实现可以是 数组 或链表;

我们常用的SGI STL,如果没有指定底层实现的话,默认是以deque为缺省情况下栈的低层结构。

5.1 c++ STL 容器适配器简介_第2张图片

deque是一个双向队列,只要封住一段,只开通另一端就可以实现栈的逻辑了。

  • 通过指定底层容器 实现 stack 和 queue;
SGI STL中 队列底层实现缺省情况下一样使用deque实现的。

我们也可以指定vector为栈的底层实现,初始化语句如下:

std::stack<int, std::vector<int> > third; 
 // 使用vector为底层容器的栈
 
刚刚讲过栈的特性,对应的队列的情况是一样的。

队列中先进先出的数据结构,同样不允许有遍历行为,不提供迭代器, SGI STL中队列一样是以deque为缺省情况下的底部结构。

也可以指定list 为起底层实现,初始化queue的语句如下:

std::queue<int, std::list<int>> third;
 // 定义以list为底层容器的队列

4.4 栈不提供 走访功能 和 迭代器

栈提供push 和 pop 等等接口,所有元素必须符合先进后出规则,所以栈不提供走访功能,也不提供迭代器(iterator)

不像是set 或者map 提供迭代器iterator来遍历所有元素。

你可能感兴趣的:(#,C++,STL,容器适配器)