日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

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

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

STL六大組件功能與運用

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

1.8.3 SGI STL 的 編 譯 器 組 態(tài) 設(shè) 置 ( configuration )

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

  • ?<stl_Config.h>文件起始處有一份常量定義說明,然后即針對各家不同的編 譯器以及可能的不同版本,給予常量設(shè)定。從這里我們可以一窺各家編譯器對標(biāo)準(zhǔn)C++的支持程度。
  • 所謂臨時對象,就是一種無名對象(unnamed objects) >,它的出現(xiàn)如果不在程 序員的預(yù)期之下(例如任何pass by value操作都會引發(fā)copy操作,于是形成一 個臨時對象),往往造成效率上的負(fù)擔(dān)。但有時候刻意制造一些臨時對象,卻又是使程序干凈清爽的技巧。
  • 刻意制造臨時對象的方法是,在型別名稱之后直接加一對小括號,并可指定初值,例 如 Shape (3,5)或 int(8),其意義相當(dāng)于調(diào)用相應(yīng) 的constructor且不指定對象名稱
  • STL 最常將此技巧應(yīng)用于仿函數(shù)(functor)與 算法的搭配上,例如:
  • 最后一行便是產(chǎn)生function template具現(xiàn)體print<int>的一個臨時對象。 這個對象將被傳入for_each()之中起作用。當(dāng) for_each()結(jié)束時,這個臨時對 象也就結(jié)束了它的生命。
#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>()); }
  • 靜態(tài)常量整數(shù)成員在c la ss內(nèi)部直接初始化 in-class static constant integer initialization
  • 如 果 class內(nèi)含 const static integral data m e m b e r , 那么根據(jù) C + + 標(biāo)準(zhǔn)規(guī)格,
    我們可以在class之內(nèi)直接給予初值。所 謂 integral泛指所有整數(shù)型別,不單只是 指 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操作符在迭代器的實現(xiàn)上占有非常重要的地位,因為 任何~個迭代器都必須實現(xiàn)出前進(jìn)(譏er e * ” 和取值(dereference, operator*) 功能,前者還分為前置式(prefix)和后置式(postfix)兩種,有非常 規(guī)律的寫法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的不同,此行應(yīng)該有不同的操作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;//以上轉(zhuǎn)換操作告訴編譯器,你確實要將const int轉(zhuǎn)為non-const lvalue.//如果沒有這樣明白地轉(zhuǎn)型,有些編譯器會給你警告,有些更嚴(yán)格的編譯器會視為錯誤}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; }
  • 前 閉 后 開 區(qū) 間 表 示 法 [)
  • 任何一個STL算法,都需要獲得由一對迭代器(泛型指針)所標(biāo)示的區(qū)間,用以表示操作范圍。這一對迭代器所標(biāo)示的是個所謂的前閉后開區(qū)間15,以 [first, last)表示。也就是說,整個實際范圍從first開始,直到last-1.迭代器last 所指的是“最后一個元素的下一位置”。這種off by one (偏移一格,或說pass the end)的標(biāo)示法,帶來了許多方便,例如下面兩個STL算法的循環(huán)設(shè)計,就顯得干凈利落:
  • 因為 以下兩個函數(shù)都是遞增遍歷元素,所以使用 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 。)
  • 很少有人注意到,函數(shù)調(diào)用操作(C ++語法中的左右小括號)也可以被重載
  • 許多STL算法都提供了兩個版本,一個用于一般狀況(例如排序時以遞增方式排列),一個用于特殊狀況(例如排序時由使用者指定以何種特殊關(guān)系進(jìn)行排列)。像這種情況,需要用戶指定某個條件或某個策略,而條件或策略的背后由一整組操作構(gòu)成,便需要某種特殊的東西來代表這“一整組操作”
  • 代表“一整組操作”的,當(dāng)然是函數(shù)? 過去C 語言時代,欲將函數(shù)當(dāng)做參數(shù)傳遞 ,唯有通過函數(shù)指針(pointer to function,或 稱 function pointer)才能達(dá)成,例如:

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

請使用手機"掃一掃"x

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。