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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/446420.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/446420.shtml
英文地址,請注明出處:http://en.pswp.cn/news/446420.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

中科大 計算機網絡4 網絡核心Core 分組交換 電路交換

網絡核心 電路交換&#xff08;線路交換&#xff09;&#xff1a;打電話之前&#xff0c;先建立一條鏈路&#xff08;物理&#xff09; 分組交換&#xff1a;存儲轉發的方式 電路交換&#xff08;線路交換&#xff09; 通過信令&#xff08;控制信息&#xff0c;如&#xf…

STL 源碼剖析 空間配置器

以STL的運用角度而言&#xff0c;空間配置器是最不需要介紹的東西&#xff0c;它總是隱藏在一切組件&#xff08;更具體地說是指容器&#xff0c;container&#xff09; 的背后但是STL的操作對象都存放在容器的內部&#xff0c;容器離不開內存空間的分配為什么不說allocator是內…

中科大 計算機網絡7 分組延遲 分組丟失 吞吐量

分組丟失和延遲的原因 隊列太長沒有意義&#xff0c;用戶需求 排隊&#xff1a;輸出能力<到來的分組&#xff0c;需要等待 四種分組延遲 節點處理延遲&#xff1a;確定的 排隊延遲&#xff1a;隨機&#xff0c;取決于網絡情況 一個比特的傳輸時間&#xff1a; R1Mbps …

STL源碼剖析 迭代器iterator的概念 和 traits編程技法

iterator模式定義如下&#xff1a;提供一種方法&#xff0c;使之能夠依序巡訪某個 聚合物(容器)所含的各個元素&#xff0c;而又無需暴露該聚合物的內部表述方式.STL的中心思想在于&#xff1a;將數據容器(containers)和算法(algorithms)分開&#xff0c;彼此獨立設計&#xff…

中科大 計算機網絡11 應用層原理

應用層大綱 傳輸層向應用層提供的服務&#xff0c;形式是Socket API&#xff08;原語&#xff09; 一些網絡應用的例子 互聯網層次中&#xff0c;應用層協議最多 流媒體應用&#xff1a;直播 網絡核心最高的層次就是網絡層 應用進程通信方式 C/S&#xff1a; 客戶端&…

STL源碼剖析 序列式容器 vector 和 ilist

Vector list 單向鏈表 ilistlist的刪除操作&#xff0c;也只有指向被刪除元素的迭代器會失效&#xff0c;其他迭代器不會受到影響

中科大 計算機網絡5 接入網和物理媒體

接入網 接入網&#xff1a;把邊緣&#xff08;主機&#xff09;接入核心&#xff08;路由器&#xff0c;交換機&#xff09; 骨干網【連接主機和主機】和接入網中都有物理媒體 接入方式&#xff1a;有線和無線 帶寬共享/獨享 接入網&#xff1a;住宅接入modem modem調制解調…

STL源碼剖析 序列式容器 deque雙端隊列

相較于vector的內存拷貝&#xff0c;deque在內存不足時只需要進行內存的拼接操作即可&#xff0c;不需要重新配置、復制、釋放等操作&#xff0c;代價就是迭代器的架構不是一個普通的指針&#xff0c;比較復雜d e q u e 的迭代器 deque是分段連續空間。維持其“整體連續”假象…

中科大 計算機網絡6 Internet結構和ISP

互聯網的結構 端系統通過接入ISPs接入互聯網 n個ISP互相連接&#xff1a; IXP,Internet exchage point:互聯網接入點&#xff0c;互聯網交互點 ISP&#xff1a;互聯網服務提供商&#xff0c;提供接入&#xff0c;提供網絡【中國移動&#xff0c;中國電信】 ICP&#xff1a…

STL源碼剖析 Stack棧 queue隊列

隨機迭代器用于隨機數據訪問&#xff0c;所以棧stack不具備此功能

中科大 計算機網絡8 協議層次和服務模型

協議層次 協議層次&#xff1a;現實生活中的例子 分層 分層處理和實現復雜系統 圖中&#xff0c;左邊是模塊&#xff0c;右邊是分層 計算機的設計是分層&#xff0c;每一層實現一個或一組功能&#xff0c;下層向上層提供服務&#xff1b;但效率比較低 對等層實體通過協議來交換…

STL源碼剖析 heap堆結構

heap一般特指max-heap&#xff0c;即最大的元素位于heap和array的首部 heap不提供遍歷功能&#xff0c;也不提供迭代功能

中科大 計算機網絡9 互聯網歷史

總綱 計算機網絡 早期1960以前 1961-1972 NCP協議&#xff1a;相當于現在的TCP和IP協議 每個節點即是數據的源也是數據的目標

STL源碼剖析 序列式容器 slist

STL l i s t 是個雙向鏈表(double linked lis t) 。SGI STL提供了一個單向鏈 表 (single linked lis t) , 名 為 slist s l i s t 和 l i s t 的主要差別在于&#xff0c;前者的迭代器屬于單向的Forwardlterotor, 后者的迭代器屬于雙向的Bidirectional Iterator.為此&#xff0…

中科大 計算機網絡12 Web和HTTP

Web與HTTP 對象&#xff1a;web頁中其實是對象鏈接 URL&#xff1a;通用資源定位符【任何對象都可以使用URL來唯一標識】 用戶名&#xff1a;口令【支持匿名訪問&#xff0c;用戶名和口令不計】 端口&#xff1a;HTTP&#xff1a;80 FTP&#xff1a;21【使用默認端口號&#x…

STL源碼剖析 關聯式容器 樹 紅黑樹、二叉搜索樹、平衡二叉搜索樹

所謂關聯式容器&#xff0c;觀念上類似關聯式數據庫(實際上則簡單許多)&#xff1a;每筆數據(每個元素)都有一個鍵值(key)和一個實值(value) 2。當元素被插入到關聯式 容器中時&#xff0c;容器內部結構(可能是RB-tree,也可能是hash-table)便依照其鍵 值大小&#xff0c;以某種…

北京大學 軟件工程1 軟件 軟件工程 軟件開發 軟件工程框架

軟件的定義 重新定義軟件 新一代信息技術 區塊鏈 創造性思維 軟件的特點 軟件的種類 支撐軟件&#xff1a;VC&#xff0c;PyCharm等 應用軟件&#xff1a;QQ&#xff0c;微信 軟件工程的起源 軟件開發的三個階段 軟件工程概念的提出 軟件工程的定義 軟件工程將系統化&#…

java學習_Python基礎學習教程:從0學爬蟲?讓爬蟲滿足你的好奇心

Python基礎學習教程&#xff1a;從0學爬蟲&#xff1f;讓爬蟲滿足你的好奇心有必要學爬蟲嗎&#xff1f;我想&#xff0c;這已經是一個不需要討論的問題了。爬蟲&#xff0c;“有用”也“有趣”&#xff01;這個數據為王的時代&#xff0c;我們要從這個龐大的互聯網中來獲取到我…