文章目錄 一、仿函數(shù) 1,、介紹 2,、為什么要有仿函數(shù)? 3、核心 A,、仿函數(shù)的調(diào)用 B,、應(yīng)用 C、標(biāo)準(zhǔn)庫(kù)仿函數(shù) 4,、仿函數(shù)優(yōu)點(diǎn) 5,、仿函數(shù)作用 二、迭代器 1,、分類 2,、輔助函數(shù) 3、流型迭代器 一,、仿函數(shù) 1,、介紹 仿函數(shù)(Functor)又稱為函數(shù)對(duì)象(FunctionObject)是一個(gè)能行使函數(shù)功能的類,仿函數(shù)是定義了一個(gè)含有operator成員函數(shù)的對(duì)象,,可以視為一個(gè)一般的函數(shù),,只不過(guò)這個(gè)函數(shù)功能是在一個(gè)類中的運(yùn)算符operator中實(shí)現(xiàn),是一個(gè)函數(shù)對(duì)象,,它將函數(shù)作為參數(shù)傳遞的方式來(lái)使用,。 寫一個(gè)簡(jiǎn)單類,除了維護(hù)類的基本成員函數(shù)外,,只需要重載operator運(yùn)算符,。這樣既可以免去對(duì)一些公共變量的維護(hù),也可以使重復(fù)使用的代碼獨(dú)立出來(lái),,以便下次復(fù)用,。 STL中也大量涉及到仿函數(shù),有時(shí)仿函數(shù)的使用是為了函數(shù)擁有類的性質(zhì),,以達(dá)到安全傳遞函數(shù)指針,、依據(jù)函數(shù)生成對(duì)象、甚至是讓函數(shù)之間有繼承關(guān)系,、對(duì)函數(shù)進(jìn)行運(yùn)算和操作的效果,。比如STL中的容器set就使用了仿函數(shù)less,而less繼承的binary_function,,就可以看作是對(duì)于一類函數(shù)的總體聲明,,這是函數(shù)做不到的。 2,、為什么要有仿函數(shù),? 1,假如客戶有一個(gè)需求擺在我們的面前,編寫一個(gè)函數(shù):函數(shù)可以獲得斐波拉契數(shù)列每項(xiàng)的值,;每調(diào)用一次便返回一個(gè)值,;函數(shù)可根據(jù)需要重復(fù)使用,。我們之前在C語(yǔ)言中也講過(guò)斐波拉契數(shù)列,相信這個(gè)很好實(shí)現(xiàn)了,。那么我們就編寫的程序如下 點(diǎn)擊加載圖片 我們就開(kāi)心的完成任務(wù)了,,于是交給客戶了。過(guò)兩天,,客戶又給打回來(lái)了。說(shuō)是存在幾個(gè)問(wèn)題:函數(shù)一但調(diào)用就無(wú)法重來(lái),,靜態(tài)局部變量處于函數(shù)內(nèi)部,,外界無(wú)法改變。函數(shù)為全局函數(shù),,是唯一的,,無(wú)法多次獨(dú)立使用。無(wú)法指定某個(gè)具體的數(shù)列項(xiàng)作為初始值,。于是我們想著將靜態(tài)局部變量改為去全局變量,,再次重新調(diào)用時(shí),便將全局變量重新初始化,,重新如下 點(diǎn)擊加載圖片 點(diǎn)擊加載圖片 是滿足這個(gè)需求了,,但是要在使用時(shí)需要重新初始化全局變量,客戶肯定不干啊,。所以這個(gè)解決方案不可行,。于是乎,我們?cè)贑++中一個(gè)吊炸天的技術(shù)來(lái)了:函數(shù)對(duì)象,。 先來(lái)說(shuō)說(shuō)函數(shù)對(duì)象: 使用具體的類對(duì)象取代函數(shù),; 該類的對(duì)象具備函數(shù)調(diào)用的行為; 構(gòu)造函數(shù)指定具體數(shù)列項(xiàng)的起始位置,; 多個(gè)對(duì)象相互獨(dú)立的求解數(shù)列項(xiàng),。 點(diǎn)擊加載圖片 下來(lái)我們來(lái)看看最終的解決方案 點(diǎn)擊加載圖片 點(diǎn)擊加載圖片 我們看到已經(jīng)實(shí)現(xiàn)了所有需求,并且隨時(shí)想從哪個(gè)數(shù)開(kāi)始都行,。 2,,比如,有一個(gè)簡(jiǎn)單需求:統(tǒng)計(jì)一個(gè)vector 點(diǎn)擊加載圖片 其實(shí),統(tǒng)計(jì)容器中某個(gè)元素的數(shù)量,,C++中有一個(gè)函數(shù)count 點(diǎn)擊加載圖片 對(duì)于上面的統(tǒng)計(jì)元素個(gè)數(shù)沒(méi)有拓展性,。比如:統(tǒng)計(jì)v中元素大于于3的元素個(gè)數(shù)呢?為此我們必須再設(shè)計(jì)一個(gè)greater_count函數(shù): 點(diǎn)擊加載圖片 這樣寫就很麻煩,,我只需要改變一下規(guī)則,,就需要多一個(gè)函數(shù),,咱們可以把里面的比較規(guī)則,寫成一個(gè)函數(shù)(可調(diào)用的對(duì)象),通過(guò)傳參實(shí)現(xiàn)比較,。 點(diǎn)擊加載圖片 點(diǎn)擊加載圖片 這樣是不是就輕松很多了,,但是這里的統(tǒng)計(jì)元素3,我們要通過(guò)count_if傳到比較函數(shù)里面去,,非常的丑陋對(duì)不對(duì),。有一種寫法,可以不通過(guò)參數(shù)傳進(jìn)去,。 首先,,刪掉count_if中的最后一個(gè)參數(shù)val。 然后,,把equal和great稍加修改一下,。 點(diǎn)擊加載圖片 點(diǎn)擊加載圖片 或者使用lambda表達(dá)式 點(diǎn)擊加載圖片 其實(shí)lamda表達(dá)式出現(xiàn)之后(C++11),仿函數(shù)(C++98)的作用已經(jīng)被削弱了,,使用lamda會(huì)讓我們使用STL方便許多,。 對(duì)于count_if里有和我們寫的一模一樣的函數(shù),以后直接使用即可 那么使用仿函數(shù),,怎么實(shí)現(xiàn)上述功能呢,? 點(diǎn)擊加載圖片 點(diǎn)擊加載圖片 可以繼續(xù)升級(jí)~ 點(diǎn)擊加載圖片 點(diǎn)擊加載圖片 3、核心 仿函數(shù)是讓類名模仿函數(shù)調(diào)用的行為---->函數(shù)名(參數(shù)),,讓類名能夠:類名(參數(shù))方式使用 自己寫仿函數(shù)關(guān)鍵點(diǎn)在于重載運(yùn)算符,,所謂的模仿函數(shù)的行為,本質(zhì)先構(gòu)造一個(gè)無(wú)名對(duì)象,,然后通過(guò)對(duì)象隱式調(diào)用重載函數(shù) 自己寫仿函數(shù) 標(biāo)準(zhǔn)庫(kù)中的仿函數(shù)(不需要記,,自己會(huì)寫了,自己創(chuàng)造) 仿函數(shù)一般有兩個(gè)作用: 充當(dāng)比較準(zhǔn)則 充當(dāng)算法或者容器構(gòu)建的參數(shù) A,、仿函數(shù)的調(diào)用 必須加上{},,要不然解析不了,分不清楚是構(gòu)造函數(shù)還是啥 sum 點(diǎn)擊加載圖片 B,、應(yīng)用 冒泡排序函數(shù)準(zhǔn)則的寫入,,使用結(jié)構(gòu)體和類分別進(jìn)行書寫,方便理解 點(diǎn)擊加載圖片 點(diǎn)擊加載圖片 C,、標(biāo)準(zhǔn)庫(kù)仿函數(shù) 我的評(píng)價(jià)是不用記,,用到的時(shí)候自己寫一個(gè)或者查一下,標(biāo)準(zhǔn)庫(kù)的太多了,,還比較難記 點(diǎn)擊加載圖片 點(diǎn)擊加載圖片 4,、仿函數(shù)優(yōu)點(diǎn) 如果可以用仿函數(shù)實(shí)現(xiàn),那么你應(yīng)該用仿函數(shù),,而不要用CallBack(CallBack技術(shù)是一種編程技術(shù),,它允許將一個(gè)函數(shù)作為參數(shù)傳遞給另一個(gè)函數(shù),,以便在需要時(shí)執(zhí)行該函數(shù)。這種技術(shù)通常用于事件處理程序和異步編程中,。),。原因在于: 仿函數(shù)可以不帶痕跡地傳遞上下文參數(shù)。而CallBack技術(shù)通常使用一個(gè)額外的void*參數(shù)傳遞,。這也是多數(shù)人認(rèn)為CallBack技術(shù)丑陋的原因,。 仿函數(shù)技術(shù)可以獲得更好的性能,這點(diǎn)直觀來(lái)講比較難以理解,。 5,、仿函數(shù)作用 仿函數(shù)通常有下面四個(gè)作用: 作為排序規(guī)則,在一些特殊情況下排序是不能直接使用運(yùn)算符<或者>時(shí),,可以使用仿函數(shù)。 作為判別式使用,,即返回值為bool類型,。 同時(shí)擁有多種內(nèi)部狀態(tài),比如返回一個(gè)值得同時(shí)并累加,。 作為算法for_each的返回值使用,。 二、迭代器 1,、分類 迭代器是一個(gè)類中類,,讓類中類對(duì)象模仿指針的行為,迭代器通常是用來(lái)訪問(wèn)容器的 點(diǎn)擊加載圖片 按照功能上來(lái)說(shuō)分為三類: 正向迭代器 雙向迭代器:listsetmap 隨機(jī)訪問(wèn)迭代器:array,vector,deque 注意點(diǎn):stack與queue以及priority_queue不支持迭代器訪問(wèn) 點(diǎn)擊加載圖片 點(diǎn)擊加載圖片 2,、輔助函數(shù) advance(iter,n):移動(dòng) distance(beginPos,endPos):元素個(gè)數(shù) iter_swap(first,second):交換 點(diǎn)擊加載圖片 點(diǎn)擊加載圖片 3,、流型迭代器 輸出流型迭代器 ostream_iteratorobject(ostream&out); ostream_iteratorobject(ostream&out,constchar*str); object=value:等效cout< 輸入流型迭代器istream_iteratorobject;//End-of-stream istream_iteratorobject(istream&in); *object等效cin操作 點(diǎn)擊加載圖片 點(diǎn)擊加載圖片 |
|