C++筆記七(STL與泛型編程)

標(biāo)準(zhǔn)庫源代碼在計(jì)算機(jī)中的分布

本機(jī)所用開發(fā)環(huán)境為visual studio 2013(包含了VC)亿柑,其中C/C++所用的工具庫包含在VC里面。


標(biāo)準(zhǔn)庫分布.png

標(biāo)準(zhǔn)庫 分布.png

OOP(面向?qū)ο缶幊蹋¬S GP(泛型編程)

  • OOP企圖將dates和methods關(guān)聯(lián)在一起
    • list不能使用全局的sort()排序庇勃,因?yàn)槿謘ort()需要的是隨機(jī)訪問迭代器,例如first+(last-first)/2這樣的只有RandomAccessIterator才能如此操作槽驶,而list因?yàn)閮?nèi)存模型的原因责嚷,不是連續(xù)空間,不能有iterator+5這種操作掂铐,所以它不能提供這種迭代器罕拂。
    • vector揍异、deque等容器都提供RandomAccessIterator。
template<class T,class Alloc=alloc>
class list{
...
    void sort();
}
  • GP卻是將datas和methods分開來爆班,這樣做的好處是:
    • Containers和Algorithms團(tuán)隊(duì)可各自閉門造車衷掷,其間以Iterator溝通即可。
    • Algorithms通過Iterators確定操作范圍柿菩,并通過Iterators取用Container元素戚嗅。
//Data Structures(Containers)
template<class T,class Alloc=alloc>
class vector{
...
};

//Alorithms
template<typename _RandomAccessIterator>
inline void
sort(_RandomAccessIterator _first,_RandomAccessIterator _last)
{
    ...
}
  • 所有algorithms,其內(nèi)最終涉及元素本身的操作碗旅,無非就是比大小
bool strLonger(const string& s1,const string& s2) {return s1.size() < s2.size();}

cout<<"max of zoo and hello:"<<max(string("zoo"),string("hello"))<<endl;   //max調(diào)用函數(shù)1
cout<<"longest of zoo and hello:"<<max(string("zoo"),string("hello"),strLonger)<<endl;   //max調(diào)用函數(shù)2

template<class T>     //函數(shù)1
inline const T& max(const T& a,const T& b){
  return a<b ? b:a;
}
template<class T,class Compare>    //函數(shù)2
inline const T& max(const T& a,const T& b,Compare comp){
  return comp(a,b)?b:a;
}

分配器

  • operator new()追究到底最后調(diào)用的是C函數(shù)庫中malloc()函數(shù)
  • VC6+渡处、BC++、GCC2.9的allocator都只是以::operator new和::operator delete完成allocate()和deallocate()祟辟,沒有任何特殊設(shè)計(jì)医瘫。
//VC6使用allocator,分配512ints
int* p=allocator<int>().allocate(512,(int*)0);
allocator<int>().deallocate(p,512);

//BC5使用allocator旧困,分配512ints
int* p=allocator<int>().allocate(512);
allocator<int>().deallocate(p,512);

//G2.9使用allocator醇份,分配512bytes
void* p=alloc::allocate(512);  //也可以alloc().allocate(512);
alloc::deallocate(p,512);
  • G2.9所附的標(biāo)準(zhǔn)庫,其allocator實(shí)現(xiàn)如下:


    G2.9 allocator實(shí)現(xiàn).png
  • 其中alloc的實(shí)現(xiàn)如下圖(<stl_alloc.h>):


    alloc實(shí)現(xiàn).png
  • G4.9STL對allocator的使用:
template<typename _Tp,typename _Alloc = std::allocator< _Tp>>
class vector :protected _Vector_base<_Tp , _Alloc>
{
   ...
}
  • G4.9所附的標(biāo)準(zhǔn)庫吼具,其allocator實(shí)現(xiàn)如下:


    G4.9 allocator實(shí)現(xiàn).png

    G4.9 allocator實(shí)現(xiàn).png
  • 相比G2.9僚纷,G4.9對于allocator的寫法因?yàn)榇罅繎?yīng)用了類的繼承、復(fù)合拗盒,使得觀察者在理解allocator的實(shí)現(xiàn)上增加不少難度怖竭!

容器之間的實(shí)現(xiàn)關(guān)系與分類

  • 本圖以縮排形式表達(dá)“基層與衍生層”的關(guān)系。這里所謂衍生陡蝇,并非繼承而是復(fù)合痊臭。
  • 在C++中,slist名為forward_list,hash_set,hash_map名為unordered_set登夫,unordered_map,hash_multiset,hash_multimap名為unordered_multiset,unordered_multimap;且新添array广匙。


    容器結(jié)構(gòu)再分類.png

迭代器的設(shè)計(jì)原則和Iterator Traits的作用與設(shè)計(jì)

Iterators必須有能力回答algorithms的五個問題,也就是說Iterators必須提供五種associated types恼策。


Iterator需要遵循的原則.png

五種associated types.png

為了分離class Iterators和non-class Iterators鸦致,就產(chǎn)生了Iterator traits,并且可以通過偏特化實(shí)現(xiàn)涣楷。


Traits.png

Traits 實(shí)現(xiàn).png
  • 還有其他各式各樣的traits
    • type traits ----------------<.../C++/type_traits>
    • iterator traits-------------<.../C++/bits/stl_iterator.h>
    • char traits----------------<.../C++/bits/char_traits.h>
    • allocator traits-----------<.../C++/bits/alloc_traits.h>
    • pointer traits-------------<.../C++/bits/ptr_traits.h>
    • array traits---------------<.../C++/bits/array>

深度探索list

參考鏈接【深度探索STL】詳解 list
list 和vector 是兩個最常用的容器(序列式容器)分唾。二者最顯著的區(qū)別自然就是vector是連續(xù)線性空間,list則是不連續(xù)線性空間狮斗,相比于vector(動態(tài)數(shù)組)鳍寂,它的好處是每次插入和刪除一個元素,只需配置或釋放一個元素空間情龄,對于任何位置的元素插入或元素移除迄汛,list永遠(yuǎn)是常數(shù)時間捍壤。尺有所長,寸有所短鞍爱,list 尋址某一元素也沒有vector(常數(shù)時間)方便鹃觉。

  • list 的迭代器
    • 因?yàn)殒湵砉?jié)點(diǎn)在儲存空間中不一定是連續(xù)存在的,自然也就不能像vector一樣用普通指針作為迭代器睹逃。list迭代器必須有能力指向list的節(jié)點(diǎn)盗扇,并有能力正確的遞增。遞減沉填。取值疗隶、成員存取等操作。這是作為任何一個容器的迭代器必須具備的翼闹。對于非連續(xù)空間的遞增斑鼻,遞減等操作自然是針對該容器的屬性來的,就list而言猎荠,則是指向上一個節(jié)點(diǎn)坚弱,下一個節(jié)點(diǎn),以及獲取指定節(jié)點(diǎn)关摇。
      STL list是一個雙向鏈表荒叶,迭代器必須具備前移,后移的能力输虱,所以list提供的是bidirectional iterator (雙向一個個移動)些楣。關(guān)于迭代器的分類,參見STL迭代器宪睹。vector是隨機(jī)迭代器類型(random access iterator)戈毒,這也是符合vector 可隨機(jī)存取的能力。
struct _List_iterator_base {  
    typedef size_t                     size_type;  
    typedef ptrdiff_t                  difference_type;  
    typedef bidirectional_iterator_tag iterator_category;  
  
    _List_node_base* _M_node;  
  
    //構(gòu)造函數(shù)  
    _List_iterator_base(_List_node_base* __x) : _M_node(__x) {}  
    _List_iterator_base() {}  
  
    //增加和減少横堡,就是指向上一個節(jié)點(diǎn)和下一個節(jié)點(diǎn)  
    void _M_incr() { _M_node = _M_node->_M_next; }  
    void _M_decr() { _M_node = _M_node->_M_prev; }  
  
    //運(yùn)算符重載  
    bool operator==(const _List_iterator_base& __x) const {  
        return _M_node == __x._M_node;  
    }  
    bool operator!=(const _List_iterator_base& __x) const {  
        return _M_node != __x._M_node;  
    }  
};  
  
template<class _Tp, class _Ref, class _Ptr>  
struct _List_iterator : public _List_iterator_base {  
    typedef _List_iterator<_Tp, _Tp&, _Tp*>             iterator;  
    typedef _List_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;  
    typedef _List_iterator<_Tp, _Ref, _Ptr>             _Self;  
  
    typedef _Tp value_type;  
    typedef _Ptr pointer;  
    typedef _Ref reference;  
    typedef _List_node<_Tp> _Node;  
  
    //下面是子類指針賦值給父類指針,is-a原則(反過來不行)  
    _List_iterator(_Node* __x) : _List_iterator_base(__x) {}  
    _List_iterator() {}  
    _List_iterator(const iterator& __x) : _List_iterator_base(__x._M_node) {}  
  
    //對迭代器取值冠桃,獲取節(jié)點(diǎn)的數(shù)據(jù)  
    reference operator*() const { return ((_Node*)_M_node)->_M_data; }  
  
    //對迭代器的成員存取命贴,返回的是地址  
#ifndef __SGI_STL_NO_ARROW_OPERATOR  
    pointer operator->() const { return &(operator*()); }  
#endif /* __SGI_STL_NO_ARROW_OPERATOR */  
  
    //前綴和后綴++和--自增自減符重載  
    _Self& operator++() {  
        this->_M_incr();  
        return *this;//返回引用,可鏈?zhǔn)讲僮? 
    }  
    _Self operator++(int) {  
        _Self __tmp = *this;  
        this->_M_incr();  
        return __tmp;//返回變量食听,不可鏈?zhǔn)讲僮? 
    }  
    _Self& operator--() {  
        this->_M_decr();  
        return *this;  
    }  
    _Self operator--(int) {  
        _Self __tmp = *this;  
        this->_M_decr();  
        return __tmp;  
    }  
};  
list iterator.png

list iterator.png

深度探索vector

vector 將其元素置于一個動態(tài)數(shù)組中加以管理胸蛛,與 array 非常類似,兩者的唯一差別在于空間運(yùn)用的靈活性樱报,array 是靜態(tài)空間葬项,一旦配置了就不能更改,當(dāng)需要容納更多的元素時(此時已越界)迹蛤,需要重新手動配置更大的 array 空間民珍,然后重新置入數(shù)據(jù)襟士。而 vector 是動態(tài)空間,在同樣的情況下嚷量,隨著元素的加入陋桂,它的內(nèi)部機(jī)制會自行擴(kuò)充空間以容納新元素。vector 同 array 一樣可以很方便的通過索引值直接存取任何一個元素蝶溶,在數(shù)組的尾端追加或移除元素均非呈壤快速(當(dāng)追加元素超出原有分配空間時,vector需要重新分配空間)抖所,但在其中間或頭部插入移除元素就比較費(fèi)時梨州,需要移動安插點(diǎn)之后的所有元素以保持原來的相對位置。


vector iterator.png

深度探索array&forward_list

與list和vector的iterator類似田轧,有一種iterator traits用以分類class Iterators和non-class Iterators暴匠。


array iterator.png

forward_list iterator.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市涯鲁,隨后出現(xiàn)的幾起案子巷查,更是在濱河造成了極大的恐慌,老刑警劉巖抹腿,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岛请,死亡現(xiàn)場離奇詭異,居然都是意外死亡警绩,警方通過查閱死者的電腦和手機(jī)崇败,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肩祥,“玉大人后室,你說我怎么就攤上這事』旌荩” “怎么了岸霹?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長将饺。 經(jīng)常有香客問我贡避,道長,這世上最難降的妖魔是什么予弧? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任刮吧,我火速辦了婚禮,結(jié)果婚禮上掖蛤,老公的妹妹穿的比我還像新娘杀捻。我一直安慰自己,他們只是感情好蚓庭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布致讥。 她就那樣靜靜地躺著仅仆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拄踪。 梳的紋絲不亂的頭發(fā)上蝇恶,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機(jī)與錄音惶桐,去河邊找鬼撮弧。 笑死,一個胖子當(dāng)著我的面吹牛姚糊,可吹牛的內(nèi)容都是我干的贿衍。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼救恨,長吁一口氣:“原來是場噩夢啊……” “哼贸辈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肠槽,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤擎淤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后秸仙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嘴拢,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年寂纪,在試婚紗的時候發(fā)現(xiàn)自己被綠了席吴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡捞蛋,死狀恐怖孝冒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拟杉,我是刑警寧澤庄涡,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站搬设,受9級特大地震影響穴店,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜焕梅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望卦洽。 院中可真熱鬧贞言,春花似錦、人聲如沸阀蒂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至酗失,卻和暖如春义钉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背规肴。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工捶闸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拖刃。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓删壮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親兑牡。 傳聞我的和親對象是個殘疾皇子央碟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容