STL(一)之概述

  標準庫提供了以下組件:string型別;數據結構;算法;數值類別;I/O類別;國際化支持類別。

STL歷史和簡介

  STL是C++的模板庫(Standard Template Library),於1994年加入C++標準。先從STL的歷史說起,STL由Alexander Stepanov創建於1979年前後,於1993年11月的ANSI/ISO C++標準委員會會議上展示其觀念,獲得熱烈迴應,最終於次年夏天完成提案,使這個巨大的計劃成爲C++標準規格的一部分。 STL是建立在泛型編程之上的,提供了六大組件:容器、算法、迭代器、仿函數、適配器、配置器。英文對應爲container,alorithm,iterator,functor,adapter,allocator。我們熟知的STL,使用率最高的,還是他們的容器container,其餘的一切幾乎都是爲了container服務的,實際上,STL的核心在於iterator。iterator充分體現了泛型編程的特性,以及開放封閉原則等思想。

  container:用來盛放數據的,字面意思是這樣,實際上,就是實現了一系列的數據結構(data construct),例如vector,list,deque,set,map等等用來存放數據。基本由class template實現。
  algorithm:算法,類似於sort,search,copy,erase等等,基本由function template實現。
  iterator:是容器和算法之間的粘合劑,“泛型指針”,將operator*,operator–,operator++等指針操作進行重載,是一種class template;所有STL容器都有自己的專屬的迭代器;
  functor:行爲類似函數,類似函數指針,從實現的角度來看,仿函數是一種重載operator()的class或class template;
  adapter:一種用來修飾container或functor或者iterator接口的東西,就是爲這些組件做出接口,和設計模式中的適配器一樣的思想,改變接口,但是實現是在後者中實現的;

通常使用兩種方法可以完成
方法一:增加一個daapter類 ,然後使其公有繼承類1私有繼承類2,然後在重寫類1的方法
方法二:增加一個daapter類 ,然後使其公有繼承類1,把類2作爲自己的子對象,然後在重寫類1的方法裏面調用類2的新方法

  allocator:負責空間配置管理,動態分配,釋放等等。
   容器通過配置器取得數據存儲空間,算法通過迭代器獲取容器內容,仿函數可以協助算法完成不同的策略變化,配接器可以修飾或套界仿函數。


版本:

  • HP實現版本,鼻祖,HewlettPackard,開源
  • P.J.Plauger版本,Visual C++採用,可讀性較低,符號命名不講究。VS的STL頭文件在文件目錄下的VC>include裏。
  • RougeWave版本,C++ Builder採用,源碼中夾雜特殊常量
  • STLport版本,提供SGI STL爲藍本的高度可移植實現版本
  • SGI STL版本,繼承HP版本,開源,被GCC採用,可讀性非常高,由於STL是模板實現,源碼在頭文件中,位於Linux下/usr/include/c++

空間配置器

  一般而言,C++內存配置/釋放操作是直接使用new/delete。爲了精密分工,STL allocate決定將這兩階段操作區分開來。內存配置操作由 alloc::allocate() 負責,內存釋放操作由 alloc::deallocate()負責;對象構造操作由::construct ( ) 負責,對象析構操作由::destroy ( ) 負責。
  STL 標準規格告訴我們,配置器定義於之中,SGI內含以下兩個文件:

#include <stl_construct.h>    // 負責內存空間的配置與釋放
#include <stl_alloc.h>    // 負責對象內容的構造與析構

  內存空間的配置/釋放與對象內容的構造/析構,分別着落在這兩個文件身上。其中<stl_construct.h>定義有兩個基本函數:構造用的construct()和析構用的 destroy( ),它們隸厲於STL標準規範。<stl_alloc.h>,定義了一、 二級配置器,彼此合作,配置器名爲 alloc。<stl_uninitialized.h>,定義了一些全局函數, 用來填充 (fill)或複製(copy)大塊內存數據,它們也都隸屬於STL標準規範:un_initialized_copy(),un_initialized_fill(),un_initialized_fil_n()這些函數雖不屬於配置器的範疇,但與對象初值設置有關。對於容器的大規模元素初值設置很有幫助。這些函數對於效率都有面面俱到的考慮,最差情況下會調用construct(),最佳情況則會使用C標準函數memmove()直接進行內存數據的移動。

空間的配置和釋放,std::alloc

  在SGI版本的STL中,空間的配置釋放都由<stl_alloc.h>負責。它的設計思想如下:

  • 向system heap要求空間
  • 考慮多線程
  • 考慮內存不足的應變措施
  • 考慮內存碎片的問題

迭代器

  STL中的迭代器是C++指針的泛化,它在算法和容器之間充當一箇中間層,爲處理不同的數據結構提供了一致的方式。迭代器也可以看作是對容器數據結構訪問的一種約束。

STL中的迭代器分類

  • 輸入迭代器(input-iterator)
      所指之物不允許外界改變,只可以讀,只可以operator++。
  • 輸出迭代器(output-iterator)
      只可以用於寫 ,只可以operator++。
  • 前向迭代器(forward iterator)
      可以做讀寫操作,只可以operator++。
  • 雙向存取迭代器(bidirectional-access-iterator)
      可以雙向做讀寫操作,即可以重載operator++,operator–。
  • 隨機存取迭代器(random-access-iterator)
      由於操作的內存是連續的,所以不僅可以重載operator++,operator–,還可以p+n等。

這裏寫圖片描述
  直線和箭頭代表的並非C++的繼承關係,而是所謂concept(概念)與refinement(強化)的關係。


迭代器相應型別(associated type)
  在此理解相應型別即迭代器所指之物的類型及其類型相關的其它類型。比如intint *等等。

  • value type
      指迭代器所指對象的型別。
  • difference type
      用來表示兩個迭代器之間的距離, 因此它也可以用來表示一個容器的最大容量 , 因爲對於連續空間的容器而言, 頭尾之間的距離就是其最大容量。如果一個泛型算法提供計數功能, 例如 STL 的 counto , 其傳回值就必須使用迭代器的 difference type:
template <class I, class T>
typename iterator__traits<I>::difference_type // 這整行是函數回返型別
count(I first, I last, const T& value){
    typename iterator_traits<I>::difference_type n = 0;
    for(;first != last; ++first)
        if (*first == value)
            ++n;
    return n;
}
  • reference type
      引用類型。
  • pointer type
      指針類型。
  • iterator_category
      迭代器分類。

容器與線程安全

  在STL容器(和大多數廠商的願望)裏對多線程支持的黃金規則已經由SGI定義,並且在它們的STL網站[21]上發佈。大體上說,你能從實現裏確定的最多是下列內容:
  多個讀取者是安全的。多線程可能同時讀取一個容器的內容,這將正確地執行。當然,在讀取時不能有任何寫入者操作這個容器。
  對不同容器的多個寫入者是安全的。多線程可以同時寫不同的容器。

算法

  STL標準中沒有區分基本算法或複雜算法,單SGI把常用的一些算法定義在<stl_algobase.h>之中,其他算法定義在<stl_algo.h>中。

  
  
  




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章