天天看點

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 容器擴充卡簡介

4.3 我們使用的STL中stack是如何實作的?

棧是以底層容器完成其所有的工作,對外提供統一的接口,底層容器可以 是vector,deque,list ,也就是說我們可以控制使用哪種容器來實作棧的功能。

是以STL中棧被歸類為container adapter(容器擴充卡)。

而 vector, deque, list 的底層實作可以是 數組 或連結清單;

我們常用的SGI STL,如果沒有指定底層實作的話,預設是以deque為預設情況下棧的低層結構。

5.1 c++ STL 容器擴充卡簡介

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來周遊所有元素。