zoukankan      html  css  js  c++  java
  • 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算法返回的值是迭代器还是谓词(函数对象)是非常重要的。




  • 相关阅读:
    推荐一个JavaScript触发器插件,可通过指定频次、指定时间内触发指定的处理函数
    TortoiseGit for windows安装与配置
    Postgresql 迁移随笔一
    三边定位 c#
    unset变量释放内存不起作用
    局域网下 连接别人的数据库授权
    iconv 参数详解
    urlencode()和rawurlencode()区别
    php数组函数
    php://input和parse_str()使用
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/6880390.html
Copyright © 2011-2022 走看看