1.源代碼分布
標(biāo)準(zhǔn)庫STL的文件位置,與所采用的編譯器有關(guān):
(1)Visual C++:...\include (例如 D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include)
(2)GNU C++:...\4.9.2\inlcude
2.OOP(Object-Oriented programming) VS GP(Generic programming)
OOP企圖將datas和methods關(guān)聯(lián)在一起
這里的list不能使用::sort()排序侵浸,這是因?yàn)?:sort()算法設(shè)計(jì)中的Iterator必須是RandomAccessIterator旺韭,而list并不是一個(gè)連續(xù)空間,在內(nèi)存中它是由指針一個(gè)一個(gè)串起來掏觉,不能使用指針加法減法区端。因此list不能使用::sort()排序。
GP卻是將datas和methods分開來澳腹,兩者之間通過迭代器聯(lián)系在一起织盼。
兩者分開的優(yōu)點(diǎn):
(1)Containers和Algorithms團(tuán)隊(duì)可各自閉門造車,其間以Iterator溝通即可酱塔;
(2)Algorithms通過Iterators確定操作范圍沥邻,并通過Iterators取用Container元素。
補(bǔ)充:
所有的algorithms羊娃,最終設(shè)計(jì)元素本身的操作唐全,無非就是比大小。比如說重新定義max函數(shù)蕊玷,根據(jù)字符長度來比大小邮利,我們就必須重寫一個(gè)比較函數(shù)弥雹。
3.源代碼閱讀
基礎(chǔ):
(1)Operator Overloading 操作符重載
(2)Templates 模板
3.1操作符重載、模板延届、特化和偏特化
這部分內(nèi)容在之前額課程中已經(jīng)講過剪勿,不再贅述。
3.2分配器
分配器(Allocator)是容器管理內(nèi)存的工具方庭,在容器申請(qǐng)內(nèi)存空間上起作用窗宦。
分配器在底層實(shí)現(xiàn)上通過operator new()和operator delete()來完成內(nèi)存分配和釋放,而operator new()和operator delete()實(shí)際上是通過調(diào)用malloc()和free()函數(shù)來實(shí)現(xiàn)操作二鳄。
operator new()和operator delete()的源代碼如下:
3.2.1 VC6的allocator
VC6所附的標(biāo)準(zhǔn)庫,其allocator實(shí)現(xiàn)如下(<xmemory>)
3.2.2 BC5的allocator
BC5所附的標(biāo)準(zhǔn)庫媒怯,其allocator實(shí)現(xiàn)如下(<memory.stl>)
3.2.3 G2.9的allocator
G2.9所附的標(biāo)準(zhǔn)庫订讼,其allocator實(shí)現(xiàn)如下(<defalloc.h>)
3.2.4 G4.9的allocator
G4.9所附的標(biāo)準(zhǔn)庫,其allocator實(shí)現(xiàn)如下:
由以上各編譯器中allocator的源代碼可以看出扇苞,無論是VC欺殿、BC還是GNU的版本中分配器實(shí)際上是通過operator new和operator delete來調(diào)用malloc和free來管理內(nèi)存。
但是在GNU2.9中鳖敷,容器實(shí)際使用的并非是allocator脖苏,而是alloc,如下圖所示定踱。
alooc的最終實(shí)現(xiàn)內(nèi)存管理也是通過malloc和free棍潘,但是可以避免其他額外開銷,比如cookie崖媚,實(shí)現(xiàn)過程如下:
(1)設(shè)計(jì)了16條鏈表亦歉,每條鏈表負(fù)責(zé)某種特定大小的區(qū)塊,比如第0條鏈表負(fù)責(zé)8個(gè)字節(jié)大小的區(qū)塊畅哑,第1條負(fù)責(zé)16個(gè)字節(jié)肴楷,以此類推,即(標(biāo)號(hào)數(shù)+1)*8荠呐;
(2)容器的元素大小都會(huì)調(diào)整到8的倍數(shù)赛蔫,比如50的會(huì)調(diào)整到56,然后交給第6條鏈表負(fù)責(zé)泥张;
(3)分配器查看鏈條有沒有掛內(nèi)存塊呵恢,如果沒有,向操作系統(tǒng)要內(nèi)存圾结,得到的內(nèi)存塊除了頭尾有cookie瑰剃,中間的每一小塊內(nèi)存都不帶cookie;
實(shí)現(xiàn)過程示意圖如下圖所示:
在GNU4.9版本以后筝野,分配器也直接調(diào)用了operator new來分配內(nèi)存晌姚,之前2.9中的alloc放入了extention allocators中粤剧,也就是__pool_alloc,如下圖所示:
3.3容器的結(jié)構(gòu)與分類
課件里面將容器的結(jié)構(gòu)和分類講得很清楚挥唠,具體如下圖所示:
3.4 容器list
3.4.1 list
G2.9的list:
G4.9的list:
3.4.2 list的iterator
G2.9的iterator:
G4.9相較于G2.9:
模板參數(shù)只有一個(gè)(易理解)抵恋;
node結(jié)構(gòu)有其parent;
node的成員的type較精確宝磨;
具體如下圖所示:
C++標(biāo)準(zhǔn)庫以header files形式呈現(xiàn):
(1)C++標(biāo)準(zhǔn)庫的header files不帶副檔名(.h)弧关,例如#include
(2)新式C header files 不帶副檔名.h,例如#include
(3)舊式C header files (帶有副檔名.h)仍然可用唤锉,例如#include
(4)新式headers內(nèi)的組件封裝于namespace “std”
using namespace std世囊;或者以 using std::cout;的形式
(5)舊式headers 內(nèi)的組件不封裝于namespace "std"
在標(biāo)準(zhǔn)庫中,標(biāo)準(zhǔn)模板庫STL(Standard Template Library)窿祥,占據(jù)了標(biāo)準(zhǔn)庫70%株憾,80%以上的內(nèi)容。
STL的核心思想是泛型編程(Generic Programming)晒衩。
重要資源:
網(wǎng)站:
http://en.cppreference.com/w/
http://www.cplusplus.com/
https://gcc.gnu.org/
書籍:
The C++ standard Library second edition嗤瞎;
STL 源碼剖析
使用示例:
#include
#include
#include
#include
using namespace std;
int main()
{
int ia[6] = { 27, 210, 12,47, 109, 83 };
vector> vi(ia, ia + 6);
cout << count_if(vi.begin(), vi.end(),
not1(bind2nd(less(), 40)));
return 0;
}
3.容器的相關(guān)知識(shí)
3.1容器的結(jié)構(gòu)與分類
容器按在內(nèi)存中的存儲(chǔ)結(jié)構(gòu)分為三種:順序容器(Sequence Container)听系、關(guān)聯(lián)容器(Associative Container)贝奇、和無序容器(Unordered Container)。其中的無序容器是C++ 11提出的靠胜,實(shí)際上無序容器也屬于關(guān)聯(lián)容器掉瞳,使用哈希表構(gòu)成。
3.2順序容器
順序容器:它將單一類型元素聚集起來成為容器髓帽,然后根據(jù)位置來存儲(chǔ)和訪問這些元素菠赚。
標(biāo)準(zhǔn)庫提供了一下幾種順序容器:array、vector郑藏、list衡查、forward_list、slist必盖、deque拌牲、stack和queue,他們的差別在于訪問元素訪問元素的方式歌粥,以及添加或刪除元素相關(guān)操作的運(yùn)行代價(jià)塌忽。array是C++11的新內(nèi)容,功能比內(nèi)置數(shù)組更加強(qiáng)大失驶,可以以對(duì)象為單位存儲(chǔ)數(shù)據(jù)土居,vector支持快速隨機(jī)訪問,list支持快速插入/刪除,deque是一個(gè)雙端隊(duì)列擦耀,queue和stack在STL中都是基于deque來實(shí)現(xiàn)棉圈。
3.2.1順序容器的常用操作
容器定義的操作非常少,只定義了構(gòu)造函數(shù)眷蜓、添加或刪除元素的操作分瘾、設(shè)置容器長度的操作以及返回指向特殊元素的迭代器的操作。其他一些有用的操作吁系,如排序德召、查找,則不是由容器類型定義汽纤,而是由標(biāo)準(zhǔn)算法定義上岗。
(1)begin和end成員
begin 和 end 操作產(chǎn)生指向容器內(nèi)第一個(gè)元素和最后一個(gè)元素的下一位置的迭代器,這兩個(gè)迭代器通常用于標(biāo)記包含容器中所有元素的迭代器范圍蕴坪。
(2)添加元素
(3)大小操作
(4)訪問元素
(5)刪除元素
(6)swap交換操作
swap 操作實(shí)現(xiàn)交換兩個(gè)容器內(nèi)所有元素的功能液茎。要交換的操作數(shù)必須是相同類型的容器,而且所存儲(chǔ)的元素類型也必須相同辞嗡。調(diào)用了 swap 函數(shù)后,右操作數(shù)原來存儲(chǔ)的元素被存放在左操作數(shù)中滞造,反之亦然续室。 該操作不會(huì)刪除或插入任何元素,而且保證在常量時(shí)間內(nèi)實(shí)現(xiàn)交換谒养。由于容器內(nèi)沒有移動(dòng)任何元素挺狰,因此迭代器不會(huì)失效。
根據(jù)課程舉幾個(gè)使用例子:
作者獲得授權(quán)买窟,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處丰泊。
3.3關(guān)聯(lián)容器
在STL中關(guān)聯(lián)容器使用紅黑樹來實(shí)現(xiàn),因?yàn)椴皇琼樞蚪Y(jié)構(gòu)始绍,因而不能使用上面提到的push和pop函數(shù)瞳购,使用insert和erase函數(shù)來實(shí)現(xiàn)元素的插入刪除操作。
關(guān)聯(lián)容器支持通過鍵來高效地查找和讀取元素亏推,兩個(gè)基本的關(guān)聯(lián)容器類型是map和set学赛。map的元素以鍵-值(key-value)對(duì)的形式組織:鍵用于元素在map中的索引,而值則表示所存儲(chǔ)和讀取的數(shù)據(jù)吞杭。set僅包含一個(gè)鍵盏浇,并有效地支持關(guān)于某個(gè)鍵是否存在的查詢。map可理解為字典芽狗,set可理解為一類元素的集合绢掰。
關(guān)聯(lián)容器和順序容器的本質(zhì)差別在于:關(guān)聯(lián)容器通過鍵(key)存儲(chǔ)和讀取元素,而順序容器則通過元素在容器中的位置順序存儲(chǔ)和訪問元素。
et 和 map 類型的對(duì)象所包含的元素都具有不同的鍵滴劲,不允許為同一個(gè)鍵添加第二個(gè)元素攻晒。如果一個(gè)鍵必須對(duì)應(yīng)多個(gè)實(shí)例,則需使用 multimap 或 multi set哑芹,這兩種類型允許多個(gè)元素?fù)碛邢嗤逆I炎辨。
根據(jù)課程舉幾個(gè)例子:
3.4無序容器
嚴(yán)格意義上講,無序容器也屬于關(guān)聯(lián)容器聪姿。