STL與泛型編程第五周學(xué)習(xí)筆記——Boolan

在完成了STL與泛型編程前四周的學(xué)習(xí)之后扼仲,有一些總結(jié)和心得在這里通過(guò)學(xué)習(xí)筆記的方式分享出來(lái),筆記我是跟著老師在視頻中所講的內(nèi)容按照順序記錄的,也不能說(shuō)是流水賬,對(duì)課程中的一些問(wèn)題還是添加了自己的理解和分析顶燕,供也在學(xué)習(xí)C++的小伙伴用作學(xué)習(xí)交流,如有理解不到位的地方辐真,歡迎批評(píng)指正糕珊。

在STL與泛型編程前幾周的課程中,老師就STL三大部件(迭代器振愿、容器捷犹、算法)的結(jié)構(gòu)與分類(lèi)都做了詳細(xì)的介紹,本周的課程老師介紹了幾種特殊的算法冕末,加深我們對(duì)如何使用算法的認(rèn)識(shí)萍歉。

一.一個(gè)萬(wàn)用的Hash Fuction

我們總是希望hash function產(chǎn)生的hash code越亂越好,盡量不要重復(fù)档桃,因此設(shè)計(jì)hash function有三種形式——設(shè)計(jì)成成員函數(shù)枪孩、設(shè)計(jì)成一般函數(shù)、以struct hash偏特化形式實(shí)現(xiàn)hash function藻肄。

這里首先采用設(shè)計(jì)成成員函數(shù)的形式蔑舞,借由variadic template將不定量的參數(shù)拆解,做到遞歸仅炊。


這種遞歸的方式運(yùn)用了數(shù)學(xué)中黃金比的概念斗幼,即0.618

第三種形式是以struct hash偏特化形式實(shí)現(xiàn)hash function,這種方式并不難理解抚垄,對(duì)不同的類(lèi)型有不同的算法得到hash code


二.Tuple用例

Tuple其實(shí)就是一堆東西組合而成的一種類(lèi)型蜕窿,是各種類(lèi)型的整合谋逻。


聲明:


直接用make_tuple賦值:


還可以用tie將合成類(lèi)型中的成分取出來(lái)分別綁定給不同的變量:


Tuple——元之組合,數(shù)之組合


不斷的繼承自己桐经,用variadic template實(shí)現(xiàn)遞歸毁兆。


三.Type traits

Since C++11,新的標(biāo)準(zhǔn)庫(kù)有幾十個(gè)type traits阴挣,在課程中气堕,老師進(jìn)行了各種type traits測(cè)試,我們寫(xiě)的class畔咧,type traits能回答我們提出的任何問(wèn)題茎芭。將class Foo,class Goo誓沸,class Zoo丟進(jìn)type traits進(jìn)行測(cè)試梅桩,發(fā)現(xiàn)type traits確實(shí)能回答各種問(wèn)題。


這里需要注意的是:&&是move_constructor

測(cè)試之后拜隧,老師還舉了用type traits實(shí)現(xiàn)is_void宿百、is_integral、is_class洪添、is_union垦页、is_pod、is_move_assignable干奢,這里代碼就不一一貼出來(lái)了痊焊。值得注意的是:對(duì)于cout,cout是一個(gè)對(duì)象律胀,自己寫(xiě)的類(lèi)型名要丟給cout則必須進(jìn)行操作符<<重載:


四.Moveable元素對(duì)于各容器速度效能的影響

Moveable對(duì)vector的影響很大宋光,比non-moveable要快很多,無(wú)論是構(gòu)造還是拷貝炭菌,對(duì)于容器vector罪佳,moveable對(duì)其效率的影響都很大,因?yàn)闃?gòu)造vector的本質(zhì)是兩倍成長(zhǎng)空間再搬運(yùn)黑低。


但是對(duì)于容器list赘艳、deque、multiset克握、unordered_multiset蕾管,moveable對(duì)其構(gòu)造效率的影響并不大,對(duì)拷貝的效率還是有巨大的影響:


這里老師寫(xiě)了一個(gè)moveable class用于測(cè)試菩暗,代碼在這里就不貼上來(lái)了掰曾,這里值得注意的是:move版本的實(shí)則是淺拷貝,所以其速度比我們熟悉的常規(guī)copy要快得多停团;而我們經(jīng)常用到的拷貝構(gòu)造是深拷貝旷坦,M C11(C1)中掏熬,C1不是臨時(shí)對(duì)象,耗時(shí)比move版本多得多秒梅;

M C12(std::move(C1))則是淺拷貝旗芬,用這種拷貝方式,必須確保之后不會(huì)再用到C1捆蜀,此時(shí)C1是一個(gè)臨時(shí)對(duì)象疮丛。因此,vector的copy ctor是容器本身的拷貝辆它。

五.Type traits衍生

本周的作業(yè)就是利用traits來(lái)實(shí)現(xiàn)類(lèi)型的篩選誊薄。介紹traits的文章很多,但感覺(jué)大部分文章的說(shuō)明都很晦澀難懂娩井,把一個(gè)并不很復(fù)雜的C++模板的應(yīng)用描述的過(guò)于復(fù)雜暇屋。因此,在這里想把自己的理解跟大家分享一下洞辣,或許我也只是掌握了一點(diǎn)traits的皮毛而已,但也希望這些皮毛能略微抓住你的眼球昙衅,帶給你一些啟發(fā)扬霜。

首先,介紹traits前而涉,回味一下C++的模板及應(yīng)用著瓶,如果你腦海里浮現(xiàn)出的只是為實(shí)現(xiàn)一些函數(shù)或類(lèi)的重用的簡(jiǎn)單模板應(yīng)用,那我要告訴你啼县,你out了材原。最近在整理一些模板的應(yīng)用方式,有時(shí)間的話(huà)會(huì)寫(xiě)出來(lái)分享給大家季眷,本文不會(huì)去詳細(xì)討論traits以外的模板的各種高級(jí)應(yīng)用余蟹。那么,言歸正傳子刮,什么是traits威酒?其實(shí)它并不是一個(gè)新的概念,上個(gè)世紀(jì)90年代中期就已經(jīng)被提出挺峡,只是到了這個(gè)世紀(jì)才在各個(gè)C++庫(kù)中被廣泛使用葵孤,而我也是在這個(gè)概念誕生十多年后才接觸到它。C++之父Bjarne Stroustrup對(duì)traits有如下的描述:

Think of a trait as a small object whose main purpose is to carry informationused by another object or algorithm to determine "policy" or"implementation details".

我不知道官方或一些書(shū)上是如何去解釋traits的橱赠,我的理解是:當(dāng)函數(shù)尤仍,類(lèi)或者一些封裝的通用算法中的某些部分會(huì)因?yàn)閿?shù)據(jù)類(lèi)型不同而導(dǎo)致處理或邏輯不同(而我們又不希望因?yàn)閿?shù)據(jù)類(lèi)型的差異而修改算法本身的封裝時(shí)),traits會(huì)是一種很好的解決方案狭姨。

本以為能很簡(jiǎn)單的描述它宰啦,誰(shuí)知道還是用了如此長(zhǎng)的句子才說(shuō)明清楚鲤嫡,相當(dāng)?shù)膽M愧。大家只要有個(gè)大概的概念就ok了绑莺,甚至即使完全沒(méi)概念也沒(méi)關(guān)系暖眼,下面會(huì)通過(guò)實(shí)際代碼來(lái)說(shuō)明。

先看這樣一個(gè)例子纺裁。如果有一個(gè)模板類(lèi)Test:

[cpp]

template

class Test {

......

};

假設(shè)有這樣的需求诫肠,類(lèi)Test中的某部分處理會(huì)隨著類(lèi)型T的不同而會(huì)有所不同,比如希望判斷T是否為指針類(lèi)型欺缘,當(dāng)T為指針類(lèi)型時(shí)的處理有別于非指針類(lèi)型栋豫,怎么做?

模板里再加個(gè)參數(shù)谚殊,如下

[cpp]

template

class Test {

......// can use isPointer to judge whether T is apointer

};

然后用戶(hù)通過(guò)多傳一個(gè)模板類(lèi)型來(lái)告訴Test類(lèi)當(dāng)前T是否為指針丧鸯。(Test)

很抱歉,所有的正常點(diǎn)的用戶(hù)都會(huì)抱怨這樣的封裝嫩絮,因?yàn)橛脩?hù)不理解為什么要讓他們?nèi)リP(guān)心自己的模板類(lèi)型是否為指針丛肢,既然是Test類(lèi)本身的邏輯,為什么麻煩用戶(hù)呢剿干?

由于我們很難去限制用戶(hù)在使用模板類(lèi)時(shí)是使用指針還是基本數(shù)據(jù)類(lèi)型還是自定義類(lèi)型蜂怎,而用常規(guī)方法也沒(méi)有很好的方法去判斷當(dāng)前的T的類(lèi)型。traits怎么做呢置尔?

定義traits結(jié)構(gòu):

[cpp]

template

struct TraitsHelper {

static const bool isPointer = false;

};

template

struct TraitsHelper {

static const bool isPointer = true;

};

也許你會(huì)很困惑杠步,結(jié)構(gòu)體里就一個(gè)靜態(tài)常量,沒(méi)有任何方法和成員變量榜轿,有什么用呢幽歼?解釋一下,第一個(gè)結(jié)構(gòu)體的功能是定義所有TraitsHelper中isPointer的默認(rèn)值都是false谬盐,而第二個(gè)結(jié)構(gòu)體的功能是當(dāng)模板類(lèi)型T為指針時(shí)甸私,isPointer的值為true。也就是說(shuō)我們可以如下來(lái)判斷當(dāng)前類(lèi)型:

TraitsHelper::isPointer值為false设褐,可以得出當(dāng)前類(lèi)型int非指針類(lèi)型

TraitsHelper::isPointer值為true颠蕴,可以得出當(dāng)前類(lèi)型int*為指針類(lèi)型

也許看到這里部分人會(huì)認(rèn)為我簡(jiǎn)直是在說(shuō)廢話(huà),請(qǐng)?jiān)僮约浩肺断轮觯@樣是否就可以在上面Test類(lèi)的定義中直接使用TraitsHelper::isPointer來(lái)判斷當(dāng)前T的類(lèi)型了犀被。

[cpp]

if (TraitsHelper::isPointer)

......

else

......

再看第二個(gè)例子:

還是一個(gè)模板類(lèi)Test:

[cpp]

template

class Test {

public:

int Compute(int d);

private:

T mData;

};

它有一個(gè)Compute方法來(lái)做一些計(jì)算,具有int型的參數(shù)并返回int型的值外冀。

現(xiàn)在需求變了寡键,需要在T為int類(lèi)型時(shí),Compute方法的參數(shù)為int雪隧,返回類(lèi)型也為int西轩,當(dāng)T為float時(shí)员舵,Compute方法的參數(shù)為float,返回類(lèi)型為int藕畔,而當(dāng)T為其他類(lèi)型马僻,Compute方法的參數(shù)為T(mén),返回類(lèi)型也為T(mén)注服,怎么做呢韭邓?還是用traits的方式思考下。

[cpp]

template

struct TraitsHelper {

typedef T ret_type;

typedef T par_type;

};

template <>

struct TraitsHelper {

typedef int ret_type;

typedef int par_type;

};

template <>

struct TraitsHelper {

typedef float ret_type;

typedef int par_type;

};

然后我們?cè)侔裈est類(lèi)也更新下:

[cpp]

template

class Test {

public:

TraitsHelper::ret_typeCompute(TraitsHelper::par_type d);

private:

T mData;

};

可見(jiàn)溶弟,我們把因類(lèi)型不同而引起的變化隔離在了Test類(lèi)以外女淑,對(duì)用戶(hù)而言完全不需要去關(guān)心這些邏輯,他們甚至不需要知道我們是否使用了traits來(lái)解決了這個(gè)問(wèn)題辜御。到這里鸭你,再讓我們回過(guò)來(lái)取品味下開(kāi)始我說(shuō)的那句話(huà):當(dāng)函數(shù),類(lèi)或者一些封裝的通用算法中的某些部分會(huì)因?yàn)閿?shù)據(jù)類(lèi)型不同而導(dǎo)致處理或邏輯不同時(shí)擒权,traits會(huì)是一種很好的解決方案袱巨。最后,讓我們記住它吧菜拓,traits瓣窄,一種模板的應(yīng)用,非常非常有用的東東纳鼎。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市裳凸,隨后出現(xiàn)的幾起案子贱鄙,更是在濱河造成了極大的恐慌,老刑警劉巖姨谷,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逗宁,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡梦湘,警方通過(guò)查閱死者的電腦和手機(jī)瞎颗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)捌议,“玉大人哼拔,你說(shuō)我怎么就攤上這事“曷” “怎么了倦逐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)宫补。 經(jīng)常有香客問(wèn)我檬姥,道長(zhǎng)曾我,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任健民,我火速辦了婚禮抒巢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘秉犹。我一直安慰自己蛉谜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布凤优。 她就那樣靜靜地躺著悦陋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪筑辨。 梳的紋絲不亂的頭發(fā)上俺驶,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音棍辕,去河邊找鬼暮现。 笑死,一個(gè)胖子當(dāng)著我的面吹牛楚昭,可吹牛的內(nèi)容都是我干的栖袋。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼抚太,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼塘幅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起尿贫,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤电媳,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后庆亡,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體匾乓,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年又谋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拼缝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡彰亥,死狀恐怖咧七,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情剩愧,我是刑警寧澤猪叙,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響穴翩,放射性物質(zhì)發(fā)生泄漏犬第。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一芒帕、第九天 我趴在偏房一處隱蔽的房頂上張望歉嗓。 院中可真熱鬧,春花似錦背蟆、人聲如沸鉴分。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)志珍。三九已至,卻和暖如春垛叨,著一層夾襖步出監(jiān)牢的瞬間伦糯,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工嗽元, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留敛纲,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓剂癌,卻偏偏與公主長(zhǎng)得像淤翔,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子佩谷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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