• C++11包装器



    在这里插入图片描述

    1.当前程序的问题

    template<class T, class K>
    K useFun(T fun, K x)
    {
    	//count是一个static对象 当这个函数结束 count不会被销毁
    	static int count = 0;
    	//每次使用这个函数 输出count+1的值 
    	//如果是同一个函数 count会输出1 2 3
    	//而运行结果是 1 1 1 说明这个函数模板被实例化成3个不同的函数
    	cout << "count:" << ++count << endl;
    	//每次使用这个函数 输出count的地址
    	cout << "count:" << &count << endl;
    
    	return fun(x);//fun可能是一个函数名\函数指针\函数对象\lambda表达式
    }
    
    
    int func(int x)
    {
    	return x;
    }
    
    struct Functor
    {
    	int operator()(int x)
    	{
    		return x;
    	}
    };
    
    int main()
    {
    	// 函数指针
    	cout << useFun(func, 1) << endl;
    
    	// 函数对象
    	cout << useFun(Functor(), 2) << endl;
    
    	// lamber表达式对象
    	auto ret = useFun
    	(
    		[](int x)->int
    		{
    			return x;
    		}
    	, 3);
    	cout << ret << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    通过运行结果我们可以看到useFun函数模板被实例化了三份
    在useFun函数模板中 count是一个static对象
    当这个函数结束 count不会被销毁
    每次使用这个函数 输出count+1的值
    如果是同一个函数 count会输出1 2 3
    而运行结果是 1 1 1 说明这个函数模板被实例化成3个不同的函数
    通过count的地址也可以看出这是三个不同的count

    在这里插入图片描述

    问题来了 怎么能让useFun函数模板不被实例化成3份呢?这是包装器的作用就显现出来了

    2.包装器的引入

    2.1包装器的定义

    #include
    // 类模板原型如下
    template <class T> 
    function;
    
    template <class Ret, class... Args>
    class function<Ret(Args...)>;
    模板参数说明:
    Ret: 被调用函数的返回类型
    Args…:被调用函数的形参
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.2包装器的使用

    int fun(int a, int b)
    {
    	return a + b;
    }
    
    struct Functor
    {
    public:
    	int operator() (int a, int b)
    	{
    		return a + b;
    	}
    };
    
    class PLus
    {
    public:
    	static int plus_int(int a, int b)
    	{
    		return a + b;
    	}
    
    	double plus_double(double a, double b)
    	{
    		return a + b;
    	}
    };
    
    int main()
    {
    	function<int(int, int)> f1 = fun;
    	cout << f1(1, 2) << endl;
    
    	function<int(int, int)> f2 = Functor();
    	cout << f2(1, 2) << endl;
    
    	//静态成员函数通过类名直接访问方式
    	function<int(int, int)> f3 = PLus::plus_int;
    	cout << f3(1, 2) << endl;
    	//非静态成员函数通过类名直接访问方式
    	function<double(PLus,double, double)> f4 = &PLus::plus_double;
    	f4(PLus(), 1.1, 2.2);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    2.3包装器的出现对于2.1问题的解决

    template<class T, class K>
    T useFun(K fun, T x)
    {
    	staic int count = 0;
    	cout << "count:" << ++count << endl;
    	cout << "count:" << &count << endl;
    
    	return fun(x);
    }
    
    
    int func(int x)
    {
    	return x;
    }
    
    struct Functor
    {
    	int operator()(int x)
    	{
    		return x;
    	}
    };
    
    int main()
    {
    	// 函数指针
    	function<int(int)> f1 = func;
    	cout << useFun(f1, 1) << endl;
    
    	// 函数对象
    	function<int(int)> f2 = Functor();
    	cout << useFun(f2, 2) << endl;
    
    	// lamber表达式对象
    	function<int(int)> f3 = [](int x)->int {return x; };
    
    	cout << useFun(f3, 3) << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    在这里插入图片描述

    3.包装器的应用

    逆波兰表达式求值
    在这里插入图片描述
    在这里插入图片描述

    3.1C++98写法

    class Solution 
    {
    public:
    	//Evaluate inverse Polish notation
    	int evalRPN(vector<string>& tokens)
    	{
    		stack<long long> st;
    		for (auto& str : tokens)
    		{
    			if (str == "+" || str == "-" 
    			 || str == "*" || str == "/" )
    			{
    				long long right = st.top();
    				st.pop();
    				long long left = st.top();
    				st.pop();
    				switch (str[0])
    				{
    				case '+':
    					st.push(left + right);
    					break;
    				case '-':
    					st.push(left - right);
    					break;
    				case '*':
    					st.push(left * right);
    					break;
    				case '/':
    					st.push(left / right);
    					break;
    				}
    			}
    			else
    			{
    				st.push(stoll(str));
    			}
    		}
    		return st.top();
    	}
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    3.2C++11写法

    count()的用法

    在这里插入图片描述

    如果容器包含键等于k的元素,则为1,否则为零。成员类型size_type是一个无符号整数类型。

    下标运算符operator[ ]

    在这里插入图片描述

    如果k与容器中某个元素的键匹配,则函数将返回对其映射值的引用。如果k与容器中任何元素的键都不匹配,则函数将插入一个具有该键的新元素,并返回对其映射值的引用。请注意,即使没有为元素分配映射值(该元素是使用其默认构造函数构造的),这也会使容器大小增加一。类似的成员函数map::at在具有键的元素存在时具有相同的行为,但在不存在时抛出异常。

    lambda表达式的另一种用法

    template<class T, class K>
    T useFun(K fun, T x)
    {
    	static int count = 0;
    	cout << "count:" << ++count << endl;
    	cout << "&count:" << &count << endl;
    
    	return fun(x);
    }
    
    
    int func(int x)
    {
    	return x;
    }
    
    struct Functor
    {
    	int operator()(int x)
    	{
    		return x;
    	}
    };
    
    int main()
    {
    	// 函数指针
    	function<int(int)> f1 = func;
    	cout << "func(1) == " << func(1) << endl; 
    	cout << useFun(f1, 1) << endl;
    	cout << endl;
    
    	// 函数对象
    	function<int(int)> f2 = Functor();
    	cout << "Functor()(1) == " << Functor()(1) << endl;
    	cout << useFun(f2, 2) << endl;
    	cout << endl;
    
    	// lamber表达式对象
    	function<int(int)> f3 = [](int x)->int {return x; };
    	cout << "[](int x)->int {return x; }(1) == " << [](int x)->int {return x; }(1) << endl;
    	cout << useFun(f3, 3) << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    在这里插入图片描述

    C++11写法

    class Solution
    {
    	typedef long long Long;
    public:
    	int evalRPN(vector<string>& tokens)
    	{
    		stack<Long> st;
    		//m初始化时 插入4个数据 
    		//key分别是 + - * /
    		//value是lambda表达式 
    		//分别是对应key所能进行的运算
    		map< string, function<Long(Long, Long)> > m =
    		{
    			{"+", [](Long a, Long b) { return a + b; }},
    			{"-", [](Long a, Long b) { return a - b; }},
    			{"*", [](Long a, Long b) { return a * b; }},
    			{"/", [](Long a, Long b) { return a / b; }}
    		};
    		for (auto& e : tokens)
    		{
    			//m中只存储了+-*/四个字符 
    			//所以对于tokens中的数字count返回0
    			//对于运算符返回1
    
    			//是运算符
    			if (m.count(e))
    			{
    				Long right = st.top();
    				st.pop();
    				Long left = st.top();
    				st.pop();
    
    				//m[e]: m将e作为key值去查找 返回e对应的value
    				st.push(m[e](left, right));
    			}
    			//是数字
    			else
    				st.push(stoll(e));
    		}
    		return st.top();
    	}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
  • 相关阅读:
    信息安全结业复习题(选择 + 填空 + 简答 + 计算 + 设计 )含历年考题
    数组容器装水问题解法
    06.论Redis持久化的几种方式
    LeetCode:261. 以图判树 - Python
    互联网扫地僧精心总结,39W字上千道Java一线大厂面试题手册
    深度掌握TypeScript中的重载【函数重载、方法重载】
    [论文阅读]PV-RCNN++
    JavaScript
    [AutoSar NVM] 存储架构
    静态代理和动态代理
  • 原文地址:https://blog.csdn.net/LHRan_ran_/article/details/133930224