函数对象、函数适配器应用(仿函数)

mac2024-10-07  51

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接: https://blog.csdn.net/goldfish3/article/details/90973902

函数对象

也叫仿函数,本质是使用重载 () 运算符实现的

//函数对象通常不定义构造和析构函数 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; });

1234567891011121314151617181920212223

内建函数对象(仿函数)

#include <functional>

negate<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">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</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">&lt;&lt;</span> val <span class="token operator">&lt;&lt;</span> <span class="token string">" "</span> <span class="token operator">&lt;&lt;</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

成员函数适配器 (略略略,没觉得好用,先看看)

for_each 和 transform

int add(int val){ return val+10; } int main(){ vector<int> v = {1,2,3,4,5,6,7,8,9}; vector<int> target; target.resize(v.size());

//transform用于把一个容器中的元素,以某种规则映射到另一个容器中,但要注意的是,不会自动扩容。 //比如下面就将v中的每个元素加10,映射到target中 transform(v.begin(), v.end(), target.begin(), add); for_each(target.begin(), target.end(), myPrint); }

12345678910111213

transfrom也可以作用于将两个容器中的值以某种方式映射到第三个容器中

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

查找

/* find算法 查找元素 @param value 查找的元素 @return 返回查找元素的位置 */ find(iterator beg, iterator end, value) /* find_if算法 条件查找 @param callback 回调函数或者谓词(返回bool类型的函数对象) @return bool 查找返回true 否则false */ find_if(iterator beg, iterator end, _callback);

/* 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

排序、合并、反转

/* merge算法 容器元素合并,并存储到另一容器中 @param beg1 容器1开始迭代器 @param end1 容器1结束迭代器 @param beg2 容器2开始迭代器 @param end2 容器2结束迭代器 @param dest 目标容器开始迭代器 */ merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest) /* sort算法 容器元素排序 注意:两个容器必须是有序的 @param beg 容器1开始迭代器 @param end 容器1结束迭代器 @param _callback 回调函数或者谓词(返回bool类型的函数对象) */ sort(iterator beg, iterator end, _callback) /* random_shuffle算法 对指定范围内的元素随机调整次序 @param beg 容器开始迭代器 @param end 容器结束迭代器 */ random_shuffle(iterator beg, iterator end) /* reverse算法 反转指定范围的元素 @param beg 容器开始迭代器 @param end 容器结束迭代器 */ reverse(iterator beg, iterator end) 1234567891011121314151617181920212223242526272829

拷贝和替换

/* copy算法 将容器内指定范围的元素拷贝到另一容器中 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param dest 目标起始迭代器 */ copy(iterator beg, iterator end, iterator dest) /* replace算法 将容器内指定范围的旧元素修改为新元素 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param oldvalue 旧元素 @param oldvalue 新元素 */ replace(iterator beg, iterator end, oldvalue, newvalue) /* replace_if算法 将容器内指定范围满足条件的元素替换为新元素 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param callback函数回调或者谓词(返回Bool类型的函数对象) @param oldvalue 新元素 */ replace_if(iterator beg, iterator end, _callback, newvalue) /* swap算法 互换两个容器的元素 @param c1容器1 @param c2容器2 */ swap(container c1, container c2) 1234567891011121314151617181920212223242526272829

算数生成算法

/* accumulate算法 计算容器元素累计总和 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param value累加值 */ accumulate(iterator beg, iterator end, value) ------------------------------------------------------------------------------------- /* fill算法 向容器中添加元素 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param value t填充元素 */ fill(iterator beg, iterator end, value) 123456789101112131415

集合算法

/* set_intersection算法 求两个set集合的交集 注意:两个集合必须是有序序列 @param beg1 容器1开始迭代器 @param end1 容器1结束迭代器 @param beg2 容器2开始迭代器 @param end2 容器2结束迭代器 @param dest 目标容器开始迭代器 @return 目标容器的最后一个元素的迭代器地址 */ set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest) --------------------------------------------------------------------------------------------- /* set_union算法 求两个set集合的并集 注意:两个集合必须是有序序列 @param beg1 容器1开始迭代器 @param end1 容器1结束迭代器 @param beg2 容器2开始迭代器 @param end2 容器2结束迭代器 @param dest 目标容器开始迭代器 @return 目标容器的最后一个元素的迭代器地址 */ set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest) --------------------------------------------------------------------------------------------- /* set_difference算法 求两个set集合的差集 注意:两个集合必须是有序序列 @param beg1 容器1开始迭代器 @param end1 容器1结束迭代器 @param beg2 容器2开始迭代器 @param end2 容器2结束迭代器 @param dest 目标容器开始迭代器 @return 目标容器的最后一个元素的迭代器地址 */ set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest) 1234567891011121314151617181920212223242526272829303132333435 </div> <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e9f16cbbc2.css" rel="stylesheet"> </div>
最新回复(0)