關于實現(xiàn)STL的一點感想

在根據《STL源碼剖析》實現(xiàn)STL的過程中匙瘪,有了一點感想铆铆,這里進行記錄,給感興趣的朋友做個參考丹喻。代碼參見githubbridgeqiao

前期準備

不管對STL的熟悉程度如何薄货,有幾點是要知道的。

  1. 至少是知道大概是怎么用的碍论,用過push_back谅猾、pop_back之類的函數(shù);
  2. 熟悉C++的struct和class定義鳍悠,常用的語法赊瞬,知道template的特化和偏特化先煎,閱讀過《c++ primer》最好贼涩;
  3. 讀過《effective c++》更好巧涧,知道c++默認構造的四個函數(shù)和大概的對象內存模型(沒有虛函數(shù)的對象和有虛函數(shù)的),面向對象編程基本概念遥倦;
  4. 代碼實現(xiàn)時谤绳,最好用c++11的新特性,nullptr袒哥、using之類的缩筛,頭文件使用c++的版本,就是普通的c頭文件前加個c去掉.h堡称,比如limits.h改為climits瞎抛。

STL背景

在書中的第一章有介紹,六大組件却紧、GNU桐臊、不同的版本,1.9.1感覺沒必要細看晓殊,定義的一些宏断凶,自己實現(xiàn)代碼的話沒必要搞這么復雜,用c++11就行了巫俺,后幾個小節(jié)倒是可以細看认烁,特別是關于臨時對象的,可以參考c++的move語義和RVO介汹,減少一次拷貝析構却嗡。

空間配置器

最開始的簡單allocator可以參考我寫的一篇博客,書上的存在一點問題嘹承,當然直接忽略了也行窗价,反正和后面的沒聯(lián)系。2.2.1可以忽略赶撰,從2.2.2開始看舌镶。需要知道new operator、operator new和placement new豪娜。里面的異常處理和宏定義都可以忽略餐胀。

一級空間配置器只有在分配大于128字節(jié)時起作用,使用malloc()分配內存瘤载,然后用placement new進行構造否灾。銷毀空間時,先析構鸣奔,再free墨技。擴展閱讀c++內存管理惩阶,malloc在分配大于128KB時的實現(xiàn)。

二級空間配置器是為了減少內存碎片而使用的扣汪,使用free_list管理空閑內存断楷,以每8個字節(jié)遞增,從8字節(jié)到128字節(jié)崭别,union obj可以簡單理解為void*冬筒。大于128B,交給malloc分配茅主,小于的話舞痰,使用free_list里找個空閑的塊分配,如果free_list里面沒有空閑的塊诀姚,使用refill重新填充响牛。

refill很有意思,它不直接參與分配內存赫段,而是通過chunk_alloc在內存池分配呀打,然后根據分到的內存,將第一小塊返回給對象瑞佩,后面剩余的給串起來聚磺,放到free_list中,這里要注意炬丸,每一個小塊大小是按照8的倍數(shù)來的瘫寝,不是對象要求的大小。這個refill函數(shù)里面將obj*強轉成char*稠炬,其實可以直接用next_obj->data的焕阿,除了這里可能會用到union obj的特性,其它地方是真沒發(fā)現(xiàn)有用到的首启。

uninitialized_**幾個函數(shù)可以先實現(xiàn)暮屡,不用管type traits,按照書上的順序看就行毅桃。

迭代器和traits

那個auto_ptr可以換成shared_ptr褒纲,更有意義一點,auto_ptr過時了钥飞。重點看3.3節(jié)后面莺掠,參考SFINAE(Substitution Is Not A Error),在進行模板匹配時读宙,用最近的那個彻秆。迭代器類型定義的時候,用最強化(精細化?)的那個唇兑,定義函數(shù)模板酒朵,用最低階的那個。這個沒什么好說的扎附,最好都實現(xiàn)一遍蔫耽,加強理解。

vector

從這章到hashtable都是容器的定義及實現(xiàn)帕棉,書上是按照概述针肥、定義摘要、實際使用例子香伴、迭代器、容器構造插入刪除的順序來的具则,感覺定義摘要沒有把重點寫出來即纲,有點雜,應該主要關注容器的成員變量博肋,以及它在插入刪除時是大概怎樣操作的低斋,給讀者一個感性的認識。

通過allocator配置空間后匪凡,返回的頭指針賦值給start(類型為T*)膊畴,空間大小為n*sizeof(T),這n個元素未初始化病游,end_of_storage指向start+n的位置唇跨,也就是空間的尾部,finish指向已初始化元素的尾部衬衬。首先买猖,start和end_of_storage不變,每次插入元素滋尉,finish往后移一個元素玉控,直到finish==end_of_storage,此時狮惜,再插入元素的話高诺,會分配新的內存,然后將原來的元素進行拷貝碾篡,刪除原來的空間虱而。這里有個問題,就是內存為什么以2倍增長耽梅?博客里說linux是2倍薛窥,windows是1.5倍,以(1,2]倍增長為宜,我覺得這個沒有定數(shù)诅迷,只要不太大就行佩番。

vector的迭代器是原始指針,所以當發(fā)生插入刪除罢杉、內存變了的話趟畏,指針會失效。其它的照著實現(xiàn)就行滩租,可能要細看的是插入多個元素的函數(shù)赋秀,注意const函數(shù)的實現(xiàn)。

list

成員變量只有一個node律想,為雙向環(huán)狀鏈表猎莲,node包括值data,兩個指針prev技即、next著洼。初始時,只有一個node而叼,插入一個元素身笤,往front插入,用next指針指向新的節(jié)點葵陵,往back插入液荸,用prev指向新的節(jié)點。迭代器存放指向節(jié)點的指針脱篙,然后實現(xiàn)operator++之類的方法娇钱,目標是達到和原生裸指針的外在功能。結構比較簡單涡尘,難點在算法的實現(xiàn)上忍弛,特別是sort函數(shù),需要先實現(xiàn)swap考抄、merge函數(shù)细疚。

sort的原理如下:歸并排序,定義了carry和counter[64]對象川梅,每次carry從原來的list中取一個元素疯兼,放到count[0]中,從count[0]開始贫途,如果滿2個元素吧彪,將這兩個給count[1],然后如果count[1]滿4個元素丢早,給count[2]姨裸,依次類推秧倾。

count列表 初始化 第1輪 第2輪 第3輪
count[0] 0 | 0 1 | 0 0 | 0 1 | 0
count[1] 0 | 0 0 | 0 1 | 0 0 | 0
count[2] 0 | 0 0 | 0 0 | 0 1 | 0

0表示count[i]未滿2^i個元素,1表示滿傀缩。例如第二輪那先,往count[0]里面放一個元素,滿了赡艰,然后將這兩個元素給count[1]售淡,count[1]沒滿4個元素,繼續(xù)第三輪慷垮。

deque

deque這章還不錯揖闸,講解的很細,實現(xiàn)起來比較麻煩料身,特別是迭代器汤纸,為了達到RandomAccess的效果,operator+=(int n)operator-=(int n)惯驼,還有reallcate_map函數(shù)蹲嚣。

stack、queue和heap

stack和queue是容器適配器祟牲,外面套了個殼,看下接口就行抖部,可以實現(xiàn)下说贝。heap可以細看,結合網上的博客之類的慎颗,注意堆需要的迭代器為RandomAccessIterator乡恕。

rb_tree

個人覺得這章寫的不錯,樹的概念俯萎,二叉搜索樹傲宜、平衡二叉樹,紅黑樹夫啊。在5.2.2節(jié)函卒,代碼是從下到上的,不是從上到下撇眯。實現(xiàn)紅黑樹的刪除時报嵌,rebanlance參考了這篇博客,注意leftmost熊榛、rightmost和root的變化锚国。注意全黑的情況,待刪除節(jié)點為黑色玄坦,沒有孩子血筑,兄弟節(jié)點為黑色,也沒有孩子,父節(jié)點為黑色豺总,這種情況需要迭代調整顏色车伞。

hashtable

這個實現(xiàn)比較容易,如果是從前面實現(xiàn)到這個的話园欣,書本只是一個參考的作用了帖世。

算法

6.1和6.2可以看下, 然后找?guī)讉€實現(xiàn)一遍沸枯,推薦find日矫、lower_bound,其它的感興趣可以看下绑榴。

仿函數(shù)

知道unary_function和binary_function的定義哪轿,以及是如何與算法結合使用的,可以實現(xiàn)下identity和select1st翔怎,set和map可以用到窃诉。

配接器

知道三種不同的配接器,由于容器配接器前面實現(xiàn)過赤套,這里可以實現(xiàn)下insert和stream迭代器飘痛,代碼量不大。仿函數(shù)適配器也可以實現(xiàn)下容握,ptr_fun宣脉。

總結

全部寫一遍的話,基本上對STL是很熟悉了剔氏,使用起來更加得心應手塑猖,對STL的模板編程(GP?)也是有了更深的了解,當然精通是肯定談不上的-谈跛。對內存分配羊苟、type_traits更熟悉。貌似除了這些就沒了感憾。蜡励。。打基礎用的項目吧吹菱,后面可以做些面向對象方面的東西巍虫,偏網絡、多線程方面更好吧應該鳍刷。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末占遥,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子输瓜,更是在濱河造成了極大的恐慌瓦胎,老刑警劉巖芬萍,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異搔啊,居然都是意外死亡柬祠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門负芋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來漫蛔,“玉大人,你說我怎么就攤上這事旧蛾∶Ч辏” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵锨天,是天一觀的道長毯盈。 經常有香客問我,道長病袄,這世上最難降的妖魔是什么搂赋? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮益缠,結果婚禮上脑奠,老公的妹妹穿的比我還像新娘。我一直安慰自己幅慌,他們只是感情好捺信,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著欠痴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秒咨。 梳的紋絲不亂的頭發(fā)上喇辽,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音雨席,去河邊找鬼菩咨。 笑死,一個胖子當著我的面吹牛陡厘,可吹牛的內容都是我干的抽米。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼糙置,長吁一口氣:“原來是場噩夢啊……” “哼云茸!你這毒婦竟也來了?” 一聲冷哼從身側響起谤饭,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤标捺,失蹤者是張志新(化名)和其女友劉穎懊纳,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體亡容,經...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡嗤疯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了闺兢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片茂缚。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖屋谭,靈堂內的尸體忽然破棺而出脚囊,到底是詐尸還是另有隱情,我是刑警寧澤戴而,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布凑术,位于F島的核電站,受9級特大地震影響所意,放射性物質發(fā)生泄漏淮逊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一扶踊、第九天 我趴在偏房一處隱蔽的房頂上張望泄鹏。 院中可真熱鬧,春花似錦秧耗、人聲如沸备籽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽车猬。三九已至,卻和暖如春尺锚,著一層夾襖步出監(jiān)牢的瞬間珠闰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工瘫辩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留伏嗜,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓伐厌,卻偏偏與公主長得像承绸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子挣轨,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內容