[GeekBand][C++ STL與泛型編程]第六周筆記

課堂大綱
這周的課程大致上應(yīng)該是這三個(gè)部分

  1. C++模板介紹
  2. 泛型編程
  3. 容器

概述STL與泛型編程

泛型編程作為一種編程思維和想法,它是一種編程方法瞳氓,不依賴于具體的語(yǔ)言签则。
STL中主要由容器迭代器翘单,算法三個(gè)部件構(gòu)成彩届。

容器用來(lái)管理對(duì)象的集合伪冰,每一種容器都有自己的優(yōu)缺點(diǎn),儲(chǔ)存的方式等都有所不同樟蠕,使用時(shí)需根據(jù)程序的需求考慮不同容器的效率來(lái)選擇
迭代器為所有容器提供了一組公共接口贮聂,并且,每一種容器都提供自己的迭代器
STL中把數(shù)據(jù)和算法分開寨辩,賦予了STL極大的彈性
下圖演示了三個(gè)部件之間的交互關(guān)系

stl.png

可以看出寂汇,迭代器是容器和算法之間的接口,總體說(shuō)來(lái)捣染,STL使容器與算法分離,使其二者不需要相互依賴停巷,而迭代器又將算法和不同的容器stick在一起耍攘,從而使需要的算法能夠運(yùn)用到不同的容器上

Templates and Generic Programming

  • 泛型技術(shù)(Generic Programming)。比如:模板技術(shù)畔勤,RTTI技術(shù)蕾各,虛函數(shù)技術(shù),要么是試圖做到在編譯時(shí)決議庆揪,要么試圖做到運(yùn)行時(shí)決議式曲。
  • 模板(Templates)是泛型編程的基礎(chǔ)

C++模板介紹

C++主要有兩種類型的模板

  1. 類模板(Class template):使用泛型參數(shù)的類
  2. 函數(shù)模板(Function template):使用泛型參數(shù)的函數(shù)

模板實(shí)例化:顯示和隱式兩種方式
類模板實(shí)參可以是某一型別或常量(僅限int或enum)
C++類模板的聲明注意事項(xiàng):

  1. 聲明類模板和聲明函數(shù)模板類似
  2. 關(guān)鍵字class和typename都可以用,但還是傾向于使用typename
templateclass Stack{......};
template class Stack{......};

3.在類模板內(nèi)部缸榛,T可以像其他型別一樣(比如int,char等)定義成員變量和成員函數(shù)

void Push(const T const& element);
int Pop(T& element);
int Top(T& element) const;
std::vector m_Members;

泛型編程(Generic programming)

泛型編程作為一種編程思維和想法吝羞,它是一種編程方法,不依賴于具體的語(yǔ)言内颗。

  1. 關(guān)聯(lián)特性(Traits)
    Traits可以實(shí)現(xiàn)為模板類, 而關(guān)聯(lián)則是針對(duì)每個(gè)具體型別T的特化.
template< typename T > class Simg{ };
template<  > class Simg< char>{ 
public: typedef int ReturnType ;
};
template<  > class Simg< short>{ 
public: typedef int ReturnType ;
};
template<  > class Simg< int>{ 
public: typedef long ReturnType ;
};

Traits實(shí)現(xiàn): (函數(shù)定義)

template< typename T>
typename Simg< T >::ReturnType Sigma (  const T const* Start, const T const* end)
{
    Simg< T >::ReturnType type;
    type r  = ReturnType();
    return r ;                        //這里返回的就是特性的新類型}
  1. 迭代器(Iterators):迭代器是指針的泛化(generalization of pointers)
    2.1 迭代器本身是一個(gè)對(duì)象钧排,指向另外一個(gè)(可以被迭代的)對(duì)象。
    2.2 用來(lái)迭代一組對(duì)象均澳,即如果迭代器指向一組對(duì)象中的某個(gè)元素恨溜,則通過(guò)increment以后它就可以指向下一組對(duì)象中的一個(gè)元素。

迭代器是指針的泛化(generalization of pointers)

  • 迭代器本身是一個(gè)對(duì)象找前,指向另外一個(gè)(可以被迭代的)對(duì)象
  • 用來(lái)迭代一組對(duì)象糟袁,即如果迭代器指向一組對(duì)象中的某個(gè)元素,則通過(guò)increment以后它就可以指向這組對(duì)象的下一個(gè)元素
  • 在STL中迭代器是容器與算法之間的接口
  • 算法通常以迭代器作為輸入?yún)?shù)
  • 容器只要提供一種方式躺盛,可以讓迭代器訪問(wèn)容器中的元素即可项戴。

迭代器的基本思想

  1. 在STL中,迭代器最重要的思想就是分離算法和容器颗品,使之不需要相互依賴
  2. 迭代器將算法和容器粘合(stick)在一起從而使得一種算法的實(shí)現(xiàn)可以運(yùn)用到多種不同的容器上肯尺,如下面的例子所示沃缘,find算法接收一對(duì)迭代器,分別指向容器的開始和終止位置:
templalte
inline _InIt find(_InIt _First,_InIt _Last,const _Ty& _Val){
//find frist matching _Val
for(;_First != _Last;++_First)
if(*_First == _Val)
break;
return (_First);
}

容器container

總的來(lái)說(shuō)则吟,容器可以分為兩類:

  1. 順序式容器sequence containers
    排列順序與置入次序一致槐臀,例如vector,deque氓仲,list
  2. 關(guān)聯(lián)式容器associative containers
    sort群集水慨,元素的順序取決于特定的排序規(guī)則,例如set敬扛,multiset晰洒,map,multimap.

順序容器

Vector
  1. Vector是一個(gè)能夠存放任意型別的動(dòng)態(tài)數(shù)組
  2. Vector的數(shù)據(jù)結(jié)構(gòu)和操作于數(shù)組類似啥箭,在內(nèi)存中的表示是一段地址連續(xù)的空間谍珊。
  3. Vector與數(shù)組的區(qū)別在于,數(shù)組大小往往是定義的時(shí)候已經(jīng)指定急侥,而Vector支持動(dòng)態(tài)空間大小調(diào)整砌滞,隨著元素的增加,Vector內(nèi)部會(huì)自動(dòng)擴(kuò)充內(nèi)存空間坏怪。
  4. 為了使用Vector,必須用include指令包含如下文件贝润,并通過(guò)std命名空間去訪問(wèn):
#include
int main(){
std::vector v;
}

創(chuàng)建一個(gè)vector,提醒兩個(gè)比較特殊的:

vector<T> v(v,i);  //創(chuàng)建一個(gè)容量為n的T型別的vector,并都初始化為i
int a[] = {1,2,3,4,5,6,7,8,9,10};
vecotr<int> v(a,a+10);  //用數(shù)組創(chuàng)建vector

相關(guān)函數(shù):

vector我們平時(shí)使用的比較多铝宵,push_back()打掘,empty()都是常用的就不說(shuō)了,注意vector沒有push_front()鹏秋,因?yàn)閷?duì)于vector來(lái)說(shuō)如果要push_front()效率很低所以不提供這個(gè)函數(shù)尊蚁。
對(duì)于vector的at()和operator[],at會(huì)做邊界檢查侣夷,但效率比operator低枝誊。

刪除元素的操作:

clear()直接清空
pop_back()彈出尾部
erase()借助迭代器清除(傳入迭代器,也就是位置惜纸,也可以是一個(gè)范圍)
iterator erase (iterator position);
iterator erase (iterator first, iterator last);

另外叶撒,我們可以用eraze結(jié)合remove_if(定義在<algorithm>中)來(lái)刪除我們指定的元素:
首先,我們需要定義一個(gè)刪選器:用一個(gè)一元對(duì)象(unary_function)耐版,其關(guān)鍵在于重載operator():

struct ContainsString:public unary_function<string,bool>
{
ContainsString(const string& szMatch) :m_szMatch(szMatch) {}
bool operator()(const string& szStringToMatch)const {
  return (szStringToMatch.find(m_szMatch) != -1);
}

string m_szMatch;
};

還記的我們上面所說(shuō)的erase的用法么祠够,第二個(gè)用法第一個(gè)參數(shù)為eraze的起點(diǎn),我們的erase函數(shù)這樣寫:

v.erase(remove_if(
  v.begin(),
  v.end(),
  ContainsString("bushuang")
),
  v.end());

我們看remove_if的用法:

template <class ForwardIterator, class UnaryPredicate>
ForwardIterator remove_if (ForwardIterator first, ForwardIterator last,
                           UnaryPredicate pred);

第三個(gè)參數(shù)可以看到就是一個(gè)一元條件粪牲,而前兩個(gè)參數(shù)為起止迭代器古瓤,返回值是迭代器,所以現(xiàn)在就很清楚了,通過(guò)remove_if得到一個(gè)迭代器位置落君,然后從該位置把后面的東西都刪了穿香。

remove_if屬于移除性算法,根據(jù)元素值或某一準(zhǔn)則绎速,在一個(gè)區(qū)間內(nèi)移除某些元素皮获。這些算法并不能改變?cè)氐臄?shù)量,它們只是以邏輯上的思考纹冤,將原本置于后面的“不移除元素”向前移動(dòng)洒宝,覆蓋那些被移除元素而已,它們都返回新區(qū)間的邏輯終點(diǎn)(也就是最后一個(gè)“不移除元素”的下一位置)萌京。

Deque

Deque是一個(gè)能夠存放任意型別的雙向隊(duì)列雁歌,故比vector多了push_front和pop_front兩個(gè)函數(shù),而我們之前提到過(guò)vector因?yàn)樾试虿惶峁┻@兩個(gè)函數(shù)知残,所以deque必然與vector有不同的內(nèi)存管理方法:大塊的內(nèi)存分配靠瞎。
如果不是要在前面插入,一般我們不會(huì)去用Deque求妹,所以也就不多說(shuō)了较坛,其用法和vector差不多,只是效率上的差別

List

list相較于vector和deque扒最,其優(yōu)勢(shì)在于可以很快的隨意插入和刪除元素,對(duì)于插入华嘹,刪除吧趣,替換等操作,效率極高耙厚,合并list强挫,也僅僅只需要節(jié)點(diǎn)的鏈接

相關(guān)函數(shù):

void remove (const value_type& val);直接刪除指定內(nèi)容的元素
erase與上面差不多,不多說(shuō)了

具體說(shuō)一下splice

void splice (iterator position, list& x);  //entire list 
void splice (iterator position, list& x, iterator i);  //single element 
void splice (iterator position, list& x, iterator first, iterator last);  //element range

簡(jiǎn)單說(shuō)明一下參數(shù)薛躬,第二個(gè)函數(shù)剪貼單個(gè)元素俯渤,第三個(gè)參數(shù)為傳入list x的迭代器;
第三個(gè)函數(shù)后兩個(gè)參數(shù)為傳入list x的迭代器范圍
用以下代碼說(shuō)明用法:

// splicing lists
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist1, mylist2;
std::list<int>::iterator it;

// set some initial values:
for (int i=1; i<=4; ++i)
   mylist1.push_back(i);      // mylist1: 1 2 3 4

for (int i=1; i<=3; ++i)
   mylist2.push_back(i*10);   // mylist2: 10 20 30

it = mylist1.begin();
++it;                         // points to 2

mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4
                              // mylist2 (empty)
                              // "it" still points to 2 (the 5th element)

mylist2.splice (mylist2.begin(),mylist1, it);
                              // mylist1: 1 10 20 30 3 4
                              // mylist2: 2
                              // "it" is now invalid.
it = mylist1.begin();
std::advance(it,3);           // "it" points now to 30

mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end());
                              // mylist1: 30 3 4 1 10 20

std::cout << "mylist1 contains:";
for (it=mylist1.begin(); it!=mylist1.end(); ++it)
  std::cout << ' ' << *it;
std::cout << '\n';

std::cout << "mylist2 contains:";
for (it=mylist2.begin(); it!=mylist2.end(); ++it)
  std::cout << ' ' << *it;
std::cout << '\n';

return 0;
}

里面用到的advance函數(shù)作用是移動(dòng)迭代器(第二參數(shù)可為負(fù)數(shù))
我們?cè)谑褂胹plice的時(shí)候型宝,注意iterator 的位置八匠,advance函數(shù)第二參數(shù)不要讓迭代器超過(guò)范圍,否則將導(dǎo)致不可預(yù)知的問(wèn)題趴酣。另外梨树,list還有sort()與merge()函數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末岖寞,一起剝皮案震驚了整個(gè)濱河市抡四,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖指巡,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淑履,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡藻雪,警方通過(guò)查閱死者的電腦和手機(jī)秘噪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)阔涉,“玉大人缆娃,你說(shuō)我怎么就攤上這事」迮牛” “怎么了贯要?”我有些...
    開封第一講書人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)椭住。 經(jīng)常有香客問(wèn)我崇渗,道長(zhǎng),這世上最難降的妖魔是什么京郑? 我笑而不...
    開封第一講書人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任宅广,我火速辦了婚禮,結(jié)果婚禮上些举,老公的妹妹穿的比我還像新娘跟狱。我一直安慰自己,他們只是感情好户魏,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開白布驶臊。 她就那樣靜靜地躺著,像睡著了一般叼丑。 火紅的嫁衣襯著肌膚如雪关翎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評(píng)論 1 290
  • 那天鸠信,我揣著相機(jī)與錄音纵寝,去河邊找鬼。 笑死星立,一個(gè)胖子當(dāng)著我的面吹牛爽茴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播绰垂,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼闹啦,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了辕坝?” 一聲冷哼從身側(cè)響起窍奋,我...
    開封第一講書人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后琳袄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體江场,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年窖逗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了址否。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碎紊,死狀恐怖佑附,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仗考,我是刑警寧澤音同,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站秃嗜,受9級(jí)特大地震影響权均,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锅锨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一叽赊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧必搞,春花似錦必指、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至研侣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炮捧,已是汗流浹背庶诡。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咆课,地道東北人末誓。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像书蚪,于是被迫代替她去往敵國(guó)和親喇澡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

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