日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STL源码剖析 入门开始 STL概论与版本简介

發布時間:2023/12/13 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STL源码剖析 入门开始 STL概论与版本简介 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 源代碼之中時而會出現一些全局函數調用操作,尤其是定義于<stl_construct.h> 之中用于對象構造與析構的基本函數,以及定義于<stl_uninitialized.h>之 中 用 于 內 存 管 理 的 基 本 函 數 , 以及定義于<stl_algobase.h>之中的各種基本算法

STL六大組件功能與運用

  • 容 器 (containers) : 各種數據結構,如 ?vector, list , deque, set, map,用來存放數據,詳見本書4, 5 兩章。從實現的角度來看,STL容器是一種class template.就體積而言,這一部分很像冰山在海面下的比率
  • 算 法 (algorithm s): 各種常用算法如 sort, search, copy, erase - - 詳見 第 6 章。從實現的角度來看,STL算法是一種function template.
  • 迭代器(iterators): 扮演容器與算法之間的膠合劑,是所謂的“泛型指針”, 詳見第3 章.共有五種類型,以及其它衍生變化.從實現的角度來看,迭代器是一種將 operator*, operator->, operator++, operator--等指針相關操作予以重載的class template.所有STL容器都附帶有自己專屬的迭代器—— 是的,只有容器設計者才知道如何遍歷自己的元素。原生指針(native
    pointer)也是一種迭代器。
  • 仿函數(functors): 行為類似函數,可作為算法的某種策略(p olicy), 詳見 第7章。從實現的角度來看,仿函數是一種重載了 operator ()的class或 class template. 一般函數指針可視為狹義的仿函數。
  • 配 接 器 (adapters): —種用來修飾容器(containers)或仿函數(functors)或迭代器(iterators)接口的東西,詳見第8 章? 例如,STL提供的queue和 stack,雖然看似容器,其實只能算是一種容器配接器,因為它們的底部完全 借助deque,所有操作都由底層的deque供應。改變functor接口者,稱為function adapter;改變 container 接口者,稱為 container adapter;改變 iterator
    接口者,稱 為 iterator adapter.配接器的實現技術很難一言以蔽之,必須逐 —分析,詳見第8章
  • 配置器(allocators): 負責空間配置與管理,詳見第2 章。從實現的角度來 看,配置器是一個實現了動態空間配置、空間管理、空間釋放的class template.

1.8.3 SGI STL 的 編 譯 器 組 態 設 置 ( configuration )

  • 不同的編譯器對C++語言的支持程度不盡相同。作為一個希望具備廣泛移植能力的程序庫,SGI S T L 準備了一個環境組態文件<stl_config.h>,其中定義了許多常量,標示某些組態的成立與否。所有STL頭文件都會直接或間接包含這個組態文件,并以條件式寫法,讓預處理器(pre-processor)根據各個常量決定取舍哪 一段程序代碼。例如:

  • ?<stl_Config.h>文件起始處有一份常量定義說明,然后即針對各家不同的編 譯器以及可能的不同版本,給予常量設定。從這里我們可以一窺各家編譯器對標準C++的支持程度。
  • 所謂臨時對象,就是一種無名對象(unnamed objects) >,它的出現如果不在程 序員的預期之下(例如任何pass by value操作都會引發copy操作,于是形成一 個臨時對象),往往造成效率上的負擔。但有時候刻意制造一些臨時對象,卻又是使程序干凈清爽的技巧。
  • 刻意制造臨時對象的方法是,在型別名稱之后直接加一對小括號,并可指定初值,例 如 Shape (3,5)或 int(8),其意義相當于調用相應 的constructor且不指定對象名稱。
  • STL 最常將此技巧應用于仿函數(functor)與 算法的搭配上,例如:
  • 最后一行便是產生function template具現體print<int>的一個臨時對象。 這個對象將被傳入for_each()之中起作用。當 for_each()結束時,這個臨時對 象也就結束了它的生命。
#include <iostream> #include <algorithm> #include <iterator> #include <set> #include <vector> #include <functional> #include <deque>template <typename T> class print{ public:void operator() (const T& elem) {//operator() 重載std::cout << elem << std::endl;} }; int main(int argc,char* argv[]){int ia[6] = {0,1,2,3,4,5};std::vector<int>iv(ia,ia+6);std::for_each(iv.begin(),iv.end(), print<int>()); }
  • 靜態常量整數成員在c la ss內部直接初始化 in-class static constant integer initialization
  • 如 果 class內含 const static integral data m e m b e r , 那么根據 C + + 標準規格,
    我們可以在class之內直接給予初值。所 謂 integral泛指所有整數型別,不單只是 指 int。下面是一個例子:
#include <iostream> #include <algorithm> #include <iterator> #include <set> #include <vector> #include <functional> #include <deque>template <typename T> class print{ public:void operator() (const T& elem) {//operator() 重載std::cout << elem << std::endl;} };template <typename T> class testClass{ public:static const int _datai = 5;static const long _datal = 3L;static const char _datac = 'c'; }; int main(int argc,char* argv[]){std::cout << testClass<int>::_datai << std::endl;std::cout << testClass<int>::_datal << std::endl;std::cout << testClass<int>::_datac << std::endl; }
  • increm ent/decrem ent/dereference 操作符
  • increment/dereference操作符在迭代器的實現上占有非常重要的地位,因為 任何~個迭代器都必須實現出前進(譏er e * ” 和取值(dereference, operator*) 功能,前者還分為前置式(prefix)和后置式(postfix)兩種,有非常 規律的寫法14°有些迭代器具備雙向移動功能,那么就必須再提供decrement操作 符 (也分前置式和后置式兩種)。下面是一個范例:
#include <iostream> #include <algorithm> #include <iterator> #include <set> #include <vector> #include <functional> #include <deque>template <typename T> class print{ public:void operator() (const T& elem) {//operator() 重載std::cout << elem << std::endl;} };template <typename T> class testClass{ public:static const int _datai = 5;static const long _datal = 3L;static const char _datac = 'c'; };class INT{friend std::ostream& operator<<(std::ostream & os,const INT& i); public:INT(int i) : m_i(i){};//prefix : increment and then fetchINT& operator++(){++(this->m_i); //隨著class的不同,此行應該有不同的操作return *this;}//postfix : fetch and then incrementconst INT operator++(int){INT temp = *this;++(*this);return temp;}//postfix : decrement and then fetchINT& operator--(){--(this->m_i);return *this;}//postfix : fetch and then decrementconst INT operator--(int){INT temp = *this;--(*this);return temp;}//dereferenceint& operator*() const{return (int&)m_i;//以上轉換操作告訴編譯器,你確實要將const int轉為non-const lvalue.//如果沒有這樣明白地轉型,有些編譯器會給你警告,有些更嚴格的編譯器會視為錯誤}private:int m_i; };std::ostream& operator<<(std::ostream&os,const INT& i){os << '[' << i.m_i << ']';return os; }int main(int argc,char* argv[]){INT I(5);std::cout << I++;std::cout << ++I;std::cout << I--;std::cout << --I;std::cout << *I; }
  • 前 閉 后 開 區 間 表 示 法 [)
  • 任何一個STL算法,都需要獲得由一對迭代器(泛型指針)所標示的區間,用以表示操作范圍。這一對迭代器所標示的是個所謂的前閉后開區間15,以 [first, last)表示。也就是說,整個實際范圍從first開始,直到last-1.迭代器last 所指的是“最后一個元素的下一位置”。這種off by one (偏移一格,或說pass the end)的標示法,帶來了許多方便,例如下面兩個STL算法的循環設計,就顯得干凈利落:
  • 因為 以下兩個函數都是遞增遍歷元素,所以使用 InputIterator
template <class InputIterator,class T> InputIterator find(InputIterator first,InputIterator last,const T& value){while(first != last && *first!= value){return first;} }template <class InputIterator,class Function> Function for_each(InputIterator first,InputIterator last,Function f){for (; first != last;++first) {f(*first);}return f; }

  • ?function call 操 作 符 ( o p e r a to r 。)
  • 很少有人注意到,函數調用操作(C ++語法中的左右小括號)也可以被重載
  • 許多STL算法都提供了兩個版本,一個用于一般狀況(例如排序時以遞增方式排列),一個用于特殊狀況(例如排序時由使用者指定以何種特殊關系進行排列)。像這種情況,需要用戶指定某個條件或某個策略,而條件或策略的背后由一整組操作構成,便需要某種特殊的東西來代表這“一整組操作”
  • 代表“一整組操作”的,當然是函數? 過去C 語言時代,欲將函數當做參數傳遞 ,唯有通過函數指針(pointer to function,或 稱 function pointer)才能達成,例如:

  • ?但是函數指針有缺點,最重要的是它無法持有自己的狀態(所謂局部狀態,local states), 也無法達到組件技術中的可適配性(adaptability)—— 也就是無法再將某 些修飾條件加諸于其上而改變其狀態。
  • 為此,S T L 算法的特殊版本所接受的所謂“條件”或 “策略”或 “一整組操作”,都以仿函數形式呈現。所謂仿函數(functor)就是使用起來像函數一樣的東 西。如果你針對某個class進 行 operator()重載,它就成為一個仿函數。至于要 成為一個可配接的仿函數,還需要做一些額外的努力(詳見第8 章 )。
  • 上 述 的 plus<T>和 minus<T>已經非常接近STL的實現了,唯一的差別在 于 它 缺 乏 “可配接能力”。關 于 “可配接能力
template <class T> struct plus{T operator() (const T&x,const T&y) const{return x+y;} };template <class T> struct minus{T operator()(const T&x,const T&y) const{return x-y;} };int main(int argc,char* argv[]){plus<int>plus_obj{};minus<int>minus_obj{};//以下使用仿函數,就像使用一般函數一樣std::cout << plus_obj(3,5) << std::endl;std::cout << minus_obj(3,5) << std::endl;//以下直接產生仿函數的臨時對象(第一對小括號),并調用之(第二對小括號)std::cout << plus<int>()(3,5) << std::endl;std::cout << minus<int>()(5,3) << std::endl; }

請使用手機"掃一掃"x

總結

以上是生活随笔為你收集整理的STL源码剖析 入门开始 STL概论与版本简介的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。