【STL终极奥义❀解耦合思想的实现❀】函数对象、谓词与函数适配器——从for_each、transform、count_if、sort算法源码的角度分析(二)

简介: 【STL终极奥义❀解耦合思想的实现❀】函数对象、谓词与函数适配器——从for_each、transform、count_if、sort算法源码的角度分析

3.2 根据transform源码实现函数对象

根据源码分析,回调函数接口应为二元函数对象,函数返回值为一个元素,代码如下:

1. template<typename _MyType>
2. class _TransformClass
3. {
4. public:
5.  _MyType operator()(_MyType& t1, _MyType& t2)
6.  {
7.    return (t1 + t2);
8.  }
9. };
10. 
11. template<typename _MyType>
12. _MyType _TransformFunc(_MyType& t1, _MyType& t2)
13. {
14.   return (t1 + t2);
15. }

继续在主函数添加测试代码如下:

1. vector<string> v3(for_each_obj.get_count() + 1);
2. v3[6] = "end";
3. transform(v1.begin(), v1.end(), v1.begin(), v3.begin(), _TransformClass<string>());
4. for_each(v3.begin(), v3.end(), _FroEachClass<string>());
5. cout << endl;
6. vector<string>::iterator it = transform(v1.begin(), v1.end(), v1.begin(), v3.begin(), _TransformFunc<string>);
7. for_each(v3.begin(), v3.end(), _FroEachClass<string>());
8. cout << endl;
9. cout << *it << endl; //transform 返回的是: v1 + v2 最后一个元素相加后,后面的那个位置的迭代器

编译运行

通过输出结果看到,已经实现了把容器1和2相加存入第三个容器的功能。我们在源码分析中说到,transform返回容器3的输出迭代器,那么返回的迭代器位置究竟在哪呢,我们在程序进行了测试,也就是这几句程序

1. vector<string>::iterator it = transform(v1.begin(), v1.end(), v1.begin(), v3.begin(), _TransformFunc<string>);
2. for_each(v3.begin(), v3.end(), _FroEachClass<string>());
3. cout << endl;
4. cout << *it << endl; //transform 返回的是: v1 + v2 最后一个元素相加后,后面的那个位置的迭代器

通过对返回的迭代器指向的内容打印可以得出结论,transform算法返回的是v1.end()减去v1.begin()后面的一个位置,加入容器v1有6个元素,那么transform返回的应该是v3的第7个位置,具体可见程序中的说明。

4. sort算法与二元谓词

本节目标是通过sort算法实现排序功能。

4.1 sort算法源码分析

源码如下:

1. template <class _RanIt, class _Pr>
2. void sort(const _RanIt _First, const _RanIt _Last, _Pr _Pred) { // order [_First, _Last), using _Pred
3.  _Adl_verify_range(_First, _Last);
4.  const auto _UFirst = _Get_unwrapped(_First);
5.  const auto _ULast = _Get_unwrapped(_Last);
6.  _Sort_unchecked(_UFirst, _ULast, _ULast - _UFirst, _Pass_fn(_Pred));
7. }
1. template <class _RanIt, class _Pr>
2. void _Sort_unchecked(_RanIt _First, _RanIt _Last, _Iter_diff_t<_RanIt> _Ideal, _Pr _Pred) {
3. // order [_First, _Last), using _Pred
4.     _Iter_diff_t<_RanIt> _Count;
5. while (_ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal) { // divide and conquer by quicksort
6. auto _Mid = _Partition_by_median_guess_unchecked(_First, _Last, _Pred);
7. // TRANSITION, VSO#433486
8.         _Ideal = (_Ideal >> 1) + (_Ideal >> 2); // allow 1.5 log2(N) divisions
9. 
10. if (_Mid.first - _First < _Last - _Mid.second) { // loop on second half
11.             _Sort_unchecked(_First, _Mid.first, _Ideal, _Pred);
12.             _First = _Mid.second;
13.         } else { // loop on first half
14.             _Sort_unchecked(_Mid.second, _Last, _Ideal, _Pred);
15.             _Last = _Mid.first;
16.         }
17.     }
18. 
19. if (_ISORT_MAX < _Count) { // heap sort if too many divisions
20.         _Make_heap_unchecked(_First, _Last, _Pred);
21.         _Sort_heap_unchecked(_First, _Last, _Pred);
22.     } else if (2 <= _Count) {
23.         _Insertion_sort_unchecked(_First, _Last, _Pred); // small
24.     }
25. }

首先分析源码,sort算法实现的是排序功能,我们可以按自己的排序规则进行排序,比如对一个people类按照成员变量年龄进行排序,一个成绩管理系统,按照成绩排序等,另外STL还提供了预定义函数对象供我们使用,比如less、greater等。sort算法接收的是一个二元谓词。

4.2 根据sort源码实现二元谓词

我们实现从大到小排序,代码如下:

1. //二元谓词
2. template<typename _MyType>
3. class _SortClass
4. {
5. public:
6.  bool operator()(_MyType& t1, _MyType& t2)
7.  {
8.    return (t1 > t2);
9.  }
10. };
11. 
12. template<typename _MyType>
13. bool _SortFunc(_MyType& t1, _MyType& t2)
14. {
15.   return (t1 > t2);
16. }

在主函数添加如下测试代码:

1. v4.push_back(1);
2. sort(v4.begin(), v4.end(), _SortClass<int>());
3. for_each(v4.begin(), v4.end(), _FroEachClass<int>());
4. cout << endl;
5. sort(v4.begin(), v4.end(), _SortFunc<int>);
6. for_each(v4.begin(), v4.end(), _FroEachClass<int>());
7. cout << endl;

编译运行

我们还可以使用预定义函数对象实现从大到小排序

1. sort(v4.begin(), v4.end(), greater<int>()); //使用预定义函数对象
2. for_each(v4.begin(), v4.end(), _FroEachClass<int>());
3. cout << endl;

通过自定义的谓词,我们可以实现自己的数据类型的排序,这就是sort算法为我们提供的统一个排序模型。

5. 函数适配器

有时候算法中的函数对象只接收一元函数对象,但是我们想要实现的功能需要二元函数对象完成,这时我们就可以通过绑定器把一个二元函数对象和一个参数绑定在一起,适配成一元函数对象。比如,我们要用count_if实现计算int型容器中大于5的元素的个数,我们可以借用预定义函数对象greater,但是greater是一个二元谓词,我们在第二节分析过count_if源码,count_if接收的是一个一元函数对象,这时我们就可以使用绑定器bind2nd把元素5绑定到greater的第二个参数位置,把他适配为一元函数对象。

在主函数添加如下测试代码:

1. int n = 5;
2. int num = count_if(v4.begin(), v4.end(), bind2nd(greater<int>(), n));
3. //count_if 接收一元函数对象或一元谓词,我们借用二元谓词greater实现计算大于5的元素个数
4. //这时可以使用绑定器 bind2nd 把预定义函数对象greater和一个参数n适配为一元谓词
5. cout << "greater " << n << " : " << num << endl;

编译运行

大于5的个数为5,结果正确。

通过这个例子我们可以再一次体会到STL算法为我们提供的统一性,我们使用count_if算法完成了两个自己的算法,一个是计算容器中某元素的个数,一个是计算容器中大于某元素的个数。只要是我们的回到调函数功能和参数模型能匹配算法提供的模型,就可以套用该算法,这就是统一性。


相关文章
|
2月前
|
运维 监控 JavaScript
基于 Node.js 图结构的局域网设备拓扑分析算法在局域网内监控软件中的应用研究
本文探讨图结构在局域网监控系统中的应用,通过Node.js实现设备拓扑建模、路径分析与故障定位,提升网络可视化、可追溯性与运维效率,结合模拟实验验证其高效性与准确性。
171 3
|
2月前
|
存储 边缘计算 算法
【太阳能学报EI复现】基于粒子群优化算法的风-水电联合优化运行分析(Matlab代码实现)
【太阳能学报EI复现】基于粒子群优化算法的风-水电联合优化运行分析(Matlab代码实现)
|
3月前
|
机器学习/深度学习 算法 5G
【MUSIC、最大似然与克拉美-罗下界】MUSIC与ESPRIT 算法来估计到达角(AoA),并尝试推导克拉美-罗下界(CRLB)以分析其性能研究(Matlab代码实现)
【MUSIC、最大似然与克拉美-罗下界】MUSIC与ESPRIT 算法来估计到达角(AoA),并尝试推导克拉美-罗下界(CRLB)以分析其性能研究(Matlab代码实现)
118 0
|
4月前
|
编解码 算法 5G
MIMO雷达空间谱估计中Capon算法与MUSIC算法的对比分析及实现
MIMO雷达空间谱估计中Capon算法与MUSIC算法的对比分析及实现
252 2
|
4月前
|
人工智能 自然语言处理 算法
2025 年 7 月境内深度合成服务算法备案情况分析报告
2025年7月,中央网信办发布第十二批深度合成算法备案信息,全国389款产品通过备案,服务提供者占比超七成。截至7月14日,全国累计备案达3834款,覆盖文本、图像、音视频等多模态场景,广泛应用于生活服务、医疗、金融等领域。广东以135款居首,数字人、AI客服等C端应用主导,民营企业成主力,国企聚焦公共服务。随着AI政策推动,备案已成为AI产品合规上线关键环节。
|
18天前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
79 2
|
2月前
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
147 3
|
8天前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
|
2月前
|
存储 编解码 算法
【多光谱滤波器阵列设计的最优球体填充】使用MSFA设计方法进行各种重建算法时,图像质量可以提高至多2 dB,并在光谱相似性方面实现了显著提升(Matlab代码实现)
【多光谱滤波器阵列设计的最优球体填充】使用MSFA设计方法进行各种重建算法时,图像质量可以提高至多2 dB,并在光谱相似性方面实现了显著提升(Matlab代码实现)
|
8天前
|
机器学习/深度学习 算法 机器人
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)

热门文章

最新文章

下一篇
开通oss服务