本周暂论,侯老師繼續(xù)帶領(lǐng)我們深入剖析STL的源碼面褐,并理解泛型編程的奧義。
于是取胎,在此之前展哭,所需要的基礎(chǔ)必要的是
- C++基本語法
- 模板基礎(chǔ)
- 數(shù)據(jù)結(jié)構(gòu)和算法的概念
在不同的編譯器環(huán)境下,各家公司對(duì)標(biāo)準(zhǔn)庫(kù)的實(shí)現(xiàn)也不盡相同闻蛀。
Visual C++ 6.0 編譯器匪傍,可以去...\include
下面去找
GNU C++ 4.9.2編譯器,可以去...\4.9.2\include
下面去找
OOP和GP的概念得到再一次的區(qū)分和強(qiáng)調(diào)觉痛。在STL中役衡,至少是歷史版本中,幾乎沒有OOP的設(shè)計(jì)方式秧饮,都采用GP的概念進(jìn)行設(shè)計(jì)映挂。
此外泽篮,除了必須的語法基礎(chǔ),還需要知道操作符重載和Templates模板柑船,才不至于迷失在茫茫代碼中帽撑。
模板又分為類模板,函數(shù)模板,成員模板。模板又分為泛化和特化赶舆,以及偏特化躯畴。
本講,我們重點(diǎn)剖析了分配器术陶、迭代器和萃取機(jī)。
- 分配器 Allocator
分配器為STL中的容器提供分配內(nèi)存以及釋放內(nèi)存的調(diào)用接口。從源碼上看笙僚,VC6 C++、BC5 C++灵再、GCC 2.9的STL對(duì)operator new()
和operator delete()
都只完成allocate()
和deallocate()
的操作肋层,沒有任何額外特殊的設(shè)計(jì)。但是GCC 2.9有一個(gè)特殊的allocator名稱是alloc()
翎迁,它通過一串鏈表來將不同大小的元素分別存儲(chǔ)來降低開銷栋猖。這個(gè)非標(biāo)準(zhǔn)的分派器到了GCC 4.9的時(shí)候,又沒有出現(xiàn)在其任意一個(gè)容器源碼中了汪榔。但是它依然存在于庫(kù)中蒲拉,名稱變化為__pool_alloc
。
- 迭代器 Iterator
迭代器為STL中容器的元素訪問提供類似智能指針的功能痴腌。以鏈表為例雌团,list的迭代器其實(shí)是一個(gè)指針,它指向list中的某一個(gè)node所占用的內(nèi)存區(qū)塊的頭部位置衷掷。因此辱姨,當(dāng)使用者使用迭代器時(shí),迭代器要表現(xiàn)為一個(gè)指針的行為戚嗅,因此它要重載operator ++()
雨涛、operator ++(int)
、operator->()
懦胞、operator--()
替久、operator*()
等指針操作符。這里前加加和后加加要區(qū)分開來分別進(jìn)行重載躏尉,前加加允許疊加使用蚯根,后加加則不允許。
當(dāng)?shù)鞅皇褂谜呤褂脮r(shí),使用者可能會(huì)采用算法來對(duì)容器中的元素進(jìn)行操作颅拦。那么對(duì)于不同的算法蒂誉,它需要知道迭代器的某些特性,來方便的選取最經(jīng)濟(jì)的方式來實(shí)現(xiàn)其功能距帅。因此右锨,迭代器需要向算法提供它的特性,比如是否可以隨機(jī)存取碌秸,元素之間的偏移量是多少绍移,每個(gè)元素的大小等等。
但是讥电,如果使用者丟給算法的是一個(gè)指針蹂窖,那么算法就沒辦法從指針自己得到這些信息了。因?yàn)橹羔槢]有這些屬性恩敌。因此瞬测,萃取機(jī)就作為中介層出現(xiàn)了。
- 萃取機(jī) Traits
算法現(xiàn)在不直接詢問迭代器其屬性了纠炮,而是詢問萃取機(jī)涣楷。萃取機(jī)用模板來實(shí)現(xiàn),當(dāng)傳入的類型是迭代器時(shí)抗碰,任何問題都由萃取機(jī)作為中間傳話人,從迭代器那里取得并返回給算法绽乔。
當(dāng)特別的指針類型傳入到萃取機(jī)時(shí)弧蝇,萃取機(jī)就替代指針,回答算法的提問折砸。因?yàn)閭魅胫羔標(biāo)赶虻膶?duì)象類型是已知的看疗,因此萃取機(jī)自動(dòng)的告訴算法,指針的偏移量睦授、元素大小两芳、存取類型等等。
隨后去枷,分別以vector怖辆、array、forward_list容器為例删顶,分析了他們內(nèi)部的迭代器與萃取機(jī)的使用竖螃。