天天看點

從零開始學C++之STL(八):函數對象、 函數對象與容器、函數對象與算法

一、函數對象

1、函數對象(function object)也稱為仿函數(functor)

2、一個行為類似函數的對象,它可以沒有參數,也可以帶有若幹參數。

3、任何重載了調用運算符operator()的類的對象都滿足函數對象的特征

4、函數對象可以把它稱之為smart function。

5、STL中也定義了一些标準的函數對象,如果以功能劃分,可以分為算術運算、關系運算、邏輯運算三大類。為了調用這些标準函數對象,需要包含頭檔案<functional>。

二、自定義函數對象

注意:CFunObj()(); 表示先構造一個匿名對象,再調用operator();

三、函數對象與容器

在這邊舉map 容器的例子,大家都知道map 在插入元素的時候會自動排序,預設是根據key 從小到大排序,看map 的定義:

假設現在我們這樣使用 map< int, string > mapTest; 那麼預設的第三個參數 _Pr = less<int>,再者,map 繼承的其中一個類

 _Tmap_traits 中有個成員:

 _Pr  comp;// the comparator predicate for keys 

跟蹤進insert 函數,其中有這樣一句:

if (_DEBUG_LT_PRED(this->comp, _Key(_Where._Mynode()), this->_Kfn(_Val)))

已知 #define _DEBUG_LT_PRED(pred, x, y) pred(x, y) 很明顯地,comp 在這裡當作函數對象使用,傳入兩個參數,回頭看less 類的

模闆實作:

即實作了operator() 函數,左操作數小于右操作數時傳回為真。

我們也可以在定義的時候傳遞第三個參數,如map< int, string, greater<int> > mapTest; 則插入時按key 值從大到小排序(less,

 greater 都是STL内置的類,裡面實作了operator() 函數),甚至也可以自己實作一個類傳遞進去,如下面例程所示:

輸出為:

3 cccc

2 bbbb

1 aaaa

MyGreater 類并不是以模闆實作,隻是比較key 值為int 類型的大小。

四、函數對象與算法

在STL一些算法中可以傳入函數指針,實作自定義比較邏輯或者計算,同樣地這些函數也可以使用函數對象來代替,直接看例程再稍

作分析:

1 2 3 4 5

6 7 8 9 10

2

回顧for_each 的源碼,其中有這樣一句: _Func(*_ChkFirst); 也就是将周遊得到的元素當作參數傳入函數。

上面程式使用了函數對象,實際上可以這樣了解 PrintObj()(*_ChkFirst); 即 PrintObj() 是一個匿名的函數對象,傳入參

數,調用了operator() 函數進行列印輸出。使用函數對象的好處是比較靈活,比如直接使用函數Add3,那麼隻能将元素加3,而

使用函數對象Addobj(x), 想讓元素加上多少就傳遞給Addobj類,構造一個對象即可,因為它可以儲存一種狀态(類成員)。

count_if 中的 GreaterObj(3) 就類似了,将周遊的元素當作參數傳遞給operator(), 即若元素比3大則傳回為真。

五、STL内置的函數對象類

從零開始學C++之STL(八):函數對象、 函數對象與容器、函數對象與算法
從零開始學C++之STL(八):函數對象、 函數對象與容器、函數對象與算法

參考:

C++ primer 第四版

Effective C++ 3rd

C++程式設計規範