也叫仿函数,本质是使用重载 () 运算符实现的
//函数对象通常不定义构造和析构函数 class Person{ public: void operator()(){ cout << "hello" << endl; } }; int main(){ Person()(); } 12345678910上面定义了一个无参的函数对象,我们也可以定义有参数的。 相对于普通函数来说,函数对象有如下几个优点:
函数对象由于本质是一个对象,可以有自己的状态函数对象可以内联编译模板函数对象使函数对象具有通用性,这也是优点之一返回值的布尔类型的函数,一元为
class Greater{ public: bool operator()(int val){ return val > 20; } };int main(){ vector<int>v; v.push_back(10); v.push_back(20); v.push_back(30); v.push_back(40); v.push_back(50); vector<int>::iterator res = find_if(v.begin(), v.end(), Greater()); if (res != v.end()) { cout << “find one” << endl; }else{ cout << “not find” << endl; } } //lambda表达式 {}(匿名函数) for_each(v.begin(), v.end(), [](int val){ cout << val << endl; });
1234567891011121314151617181920212223negate<int> n; cout << n(10) << endl;
plus<int> p; cout << p(1,1) << endl;
1234567平时用的最多的函数对象就是 sort 中的 greater 了
int main(){ vector<int> v = {1,232,12,232,12,32,43}; <span class="token comment">//这里的 greater 就是一个函数对象</span> <span class="token function">sort</span><span class="token punctuation">(</span>v<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> v<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> greater<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//将排序后的打印出来</span> <span class="token comment">//lambda表达式 [](){}(匿名函数)</span> <span class="token function">for_each</span><span class="token punctuation">(</span>v<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> v<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token keyword">int</span> val<span class="token punctuation">)</span><span class="token punctuation">{</span>cout <span class="token operator"><<</span> val <span class="token operator"><<</span> <span class="token string">" "</span> <span class="token operator"><<</span> endl<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>}
12345678910之前往函数对象里传的参数的数量都只有一个,如果要传递两个参数呢? 这个时候就需要使用 bind2nd 函数,将 operator 的第二个参数和传入的参数绑定。
#include <functional> using namespace std; class funcObj : public binary_function<int, int, void>{ public: void operator()(int val,int addVal) const{ cout << val << " " << addVal << " " << val+addVal << endl; } }; int main(){ vector<int> v = {1,232,12,232,12,32,43}; for_each(v.begin(), v.end(), bind2nd(funcObj(), 100)); } 123456789101112如果使用bind1nd就是将 operator 的第一个参数和传入参数绑定。
但其实这里有个疑问,使用构造函数传参不是更好么 如下: 也能实现一样的效果
class funcObj{ private: int param1; public: funcObj(int param):param1(param){}; void operator()(int val){ cout << val << " " << param1 << " " << val+param1 << endl; } }; int main(){ vector<int> v = {1,232,12,232,12,32,43}; for_each(v.begin(), v.end(), funcObj(100)); } 12345678910111213不过这样一来,不够灵活? not1和not2适配器,前者用于一元函数对象,后者用于二元函数对象。 下面的代码,目的在于查找大于等于5的元素,并返回迭代器位置。
vector<int>::iterator index = find_if(v.begin(), v.end(), not1(bind2nd(less<int>(), 5))); 1成员函数适配器 (略略略,没觉得好用,先看看)
//transform用于把一个容器中的元素,以某种规则映射到另一个容器中,但要注意的是,不会自动扩容。 //比如下面就将v中的每个元素加10,映射到target中 transform(v.begin(), v.end(), target.begin(), add); for_each(target.begin(), target.end(), myPrint); }
12345678910111213transfrom也可以作用于将两个容器中的值以某种方式映射到第三个容器中
void myPrint(int val){ cout << val << " " << endl; } int add(int val1,int val2){ return val1+val2; } int main(){ vector<int> v1 = {1,2,3,4,5,6,7,8,9}; vector<int> v2 = {9,8,7,6,5,4,3,2,1}; vector<int> target; target.resize(v1.size()); //将v1和v2中的值相加,映射到v3中 transform(v1.begin(), v1.end(), v2.begin(), target.begin(), add); for_each(target.begin(), target.end(), myPrint); } 123456789101112131415/* adjacent_find算法 查找相邻重复元素 @param _callback 回调函数或者谓词(返回bool类型的函数对象) @return 返回相邻元素的第一个位置的迭代器 / adjacent_find(iterator beg, iterator end, _callback); / binary_search算法 二分查找法 注意: 在无序序列中不可用 @param value 查找的元素 @return bool 查找返回true 否则false / bool binary_search(iterator beg, iterator end, value); / count算法 统计元素出现次数 @param value回调函数或者谓词(返回bool类型的函数对象) @return int返回元素个数 / count(iterator beg, iterator end, value); / count算法 统计元素出现次数 @param callback 回调函数或者谓词(返回bool类型的函数对象) @return int返回元素个数 */ count_if(iterator beg, iterator end, _callback);
1234567891011121314151617181920212223242526272829303132333435363738