• STL算法设计理念


    函数对象:
    重载函数调用操作符的类。其对象常称为函数对象(function object),即它们是行为类似函数的对象。

    一个类对象,表现出一个函数的特征,就是通过“对象名+(參数列表)”的方式使用一个类对象,假设没有上下文,全然能够把它看作一个函数对待。
    这是通过重载类的operator()来实现的。


    “在标准库中。函数对象被广泛地使用以获得弹性”。标准库中的非常多算法都能够使用函数对象或者函数来作为自定的回调行为;
    demo

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    // 函数对象。类重载了()
    template <typename T>  
    class ShowElement
    {
    public:
    	// 重载()
    	void operator()(T &t) {
    		cout << t << endl;
    	}
    protected:
    private:
    	int n;
    };
    
    // 函数模版
    template <typename T>
    void FuncShowElement(T &t)
    {
    	cout << t << endl;
    }
    
    // 普通函数
    void FuncShowElement2(int &t)
    {
    	cout << t << endl;
    }
    
    void play01()
    {
    	int a = 10;
    	ShowElement<int> showElement;
    	showElement(a); // 函数对象的调用,非常像一个函数,所以叫仿函数
    	// 10
    
    	FuncShowElement<int>(a);
    	FuncShowElement2(a);
    	
    }
    
    int main()
    {
    	play01();
    	
    	return 0;
    }
    上面简单演示了函数对象的使用以及和普通函数定义的异同,看以下的demo。

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    // 函数对象,类重载了()
    template <typename T>
    class ShowElement
    {
    public:
    	ShowElement() 
    	{
    		n = 0;
    	}
    	// 重载()
    	void operator()(T &t) {
    		++n;
    		cout << t << ' ';
    	}
    
    	void printN()
    	{
    		cout << "n: " << n << endl;
    	}
    protected:
    private:
    	int n;
    };
    
    // 函数模版
    template <typename T>
    void FuncShowElement(T &t)
    {
    	cout << t << ' ';
    }
    
    // 普通函数
    void FuncShowElement2(int &t)
    {
    	cout << t << ' ';
    }
    
    void play01()
    {
    	int a = 10;
    	ShowElement<int> showElement;
    	showElement(a); // 函数对象的调用,非常像一个函数,所以叫仿函数
    	// 10
    
    	FuncShowElement<int>(a);
    	FuncShowElement2(a);
    
    }
    
    // 函数对象的优点
    // 函数对象属于类对象,能突破函数的概念。能保持调用状态信息
    void play02()
    {
    	vector<int> v;
    	v.push_back(1);
    	v.push_back(3);
    	v.push_back(5);
    
    	for_each(v.begin(), v.end(), ShowElement<int>()); // 匿名函数对象,匿名仿函数
    	cout << endl;
    	// 1 3 5
    
    	for_each(v.begin(), v.end(), FuncShowElement2); // 通过回调函数
    	cout << endl;
    	// 1 3 5
    
    	// 改写一下类ShowElement
    	ShowElement<int> showElement;
    	/* for_each函数原型
    
    	template<class _InIt,
    		class _Fn1> inline
    		_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
    		{	// perform function for each element
    		_DEBUG_RANGE(_First, _Last);
    		_DEBUG_POINTER(_Func);
    		_For_each(_Unchecked(_First), _Unchecked(_Last), _Func);
    
    		return (_STD move(_Func));
    		}
    	*/
    	// 能够看出for_each算法的函数对象传递是元素值传递。不是引用传递
    	for_each(v.begin(), v.end(), showElement);
    	cout << endl;
    	showElement.printN(); // 所以这里打印结果并非我们预期的3
    	// n: 0
    	
    	// 解决方式。for_each最后是把传进去的函数对象做了值返回
    	showElement = for_each(v.begin(), v.end(), showElement);
    	cout << endl;
    	showElement.printN(); // bingo
    	// n: 3
    }
    
    int main()
    {
    	//play01();
    	play02();
    
    	return 0;
    }
    结论:分清楚STL算法返回的值是迭代器还是谓词(函数对象)是非常重要的。




  • 相关阅读:
    计算机概念-shell
    数组去重复的三种方法
    CSS 自定义字体
    解决 IE 6/7 中console对象兼容性问题
    Sublime Text 3 Install Markdown Preview Plugins
    对象数组排序函数
    Ubuntu 16.04 下使用Xampp
    JavaScript 中 申明变量的方式--let 语句
    bootstrap框架 导航条组件使用
    phpstorm version 2016.2 License Server激活
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/6880390.html
Copyright © 2020-2023  润新知