日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法

發布時間:2023/11/30 c/c++ 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.csdn.net/jnu_simba/article/details/9500219

一、函數對象

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


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


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


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


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


二、自定義函數對象

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include?<iostream>
using?namespace?std;
class?CFunObj
{
public:
????void?operator()()
????{
????????cout?<<?"hello,function?object!"?<<?endl;
????}
};
int?main()
{
????CFunObj?fo;
????fo();
????CFunObj()();
????return?0;
}

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


三、函數對象與容器


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

C++ Code?
1
2
3
4
5
6
7
8
9
10
//?TEMPLATE?CLASS?map
template?<?class?_Kty,
?????????class?_Ty,
?????????class?_Pr?=?less<_Kty>,
?????????class?_Alloc?=?allocator<pair<const?_Kty,?_Ty>?>?>
class?map
????:?public?_Tree<_Tmap_traits<_Kty,?_Ty,?_Pr,?_Alloc,?false>?>
{
????//?ordered?red-black?tree?of?{key,?mapped}?values,?unique?keys
};

假設現在我們這樣使用 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 類的


模板實現:

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
//?TEMPLATE?STRUCT?less
template<class?_Ty>
struct?less
????????:?public?binary_function<_Ty,?_Ty,?bool>
{
????//?functor?for?operator<
????bool?operator()(const?_Ty?&_Left,?const?_Ty?&_Right)?const
????{
????????//?apply?operator<?to?operands
????????return?(_Left?<?_Right);
????}
};

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


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


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

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include?<map>
#include?<string>
#include?<iostream>

using?namespace?std;

struct?MyGreater
{
????bool?operator()(int?left,?int?right)
????{
????????return?left?>?right;
????}
};

int?main(void)
{
????map?<?int,?string,?/*greater<int>?*/MyGreater?>?mapTest;
????mapTest.insert(map<int,?string>::value_type(1,?"aaaa"));
????mapTest.insert(map<int,?string>::value_type(3,?"cccc"));
????mapTest.insert(map<int,?string>::value_type(2,?"bbbb"));


????for?(map?<?int,?string,?/*greater<int>?*/MyGreater?>::const_iterator?it?=?mapTest.begin();?it?!=?mapTest.end();?++it)
????{
????????cout?<<?it->first?<<?"?"?<<?it->second?<<?endl;
????}

????return?0;
}

輸出為:

3 cccc

2 bbbb

1 aaaa


MyGreater 類并不是以模板實現,只是比較key 值為int 類型的大小。


四、函數對象與算法

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

作分析:

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include?<vector>
#include?<string>
#include?<iostream>
#include?<algorithm>

using?namespace?std;

void?PrintFun(int?n)
{
????cout?<<?n?<<?'?';
}

void?Add3(int?&n)
{
????n?+=?3;
}

class?PrintObj
{
public:
????void?operator()(int?n)
????{
????????cout?<<?n?<<?'?';
????}
};

class?AddObj
{
public:
????AddObj(int?number)?:?number_(number)
????{

????}
????void?operator()(int?&n)
????{
????????n?+=?number_;
????}

private:
????int?number_;
};

class?GreaterObj
{
public:
????GreaterObj(int?number)?:?number_(number)
????{

????}
????bool?operator()(int?n)
????{
????????return?n?>?number_;
????}
private:
????int?number_;
};


int?main(void)
{
????int?a[]?=?{1,?2,?3,?4,?5};
????vector<int>?v(a,?a?+?5);

????/*for_each(v.begin(),?v.end(),?PrintFun);
????cout<<endl;*/


????for_each(v.begin(),?v.end(),?PrintObj());
????cout?<<?endl;

????/*for_each(v.begin(),?v.end(),?Add3);
????for_each(v.begin(),?v.end(),?PrintFun);
????cout<<endl;*/


????for_each(v.begin(),?v.end(),?AddObj(5));
????for_each(v.begin(),?v.end(),?PrintFun);
????cout?<<?endl;


????cout?<<?count_if(a,?a?+?5,?GreaterObj(3))?<<?endl;?//計算大于3的元素個數

????return?0;
}

輸出為:

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++ primer 第四版
Effective C++ 3rd
C++編程規范


總結

以上是生活随笔為你收集整理的从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。