C++11包装器

文章目录

  • 1.当前程序的问题
  • 2.包装器的引入
    • 2.1包装器的定义
    • 2.2包装器的使用
    • 2.3包装器的出现对于2.1问题的解决
  • 3.包装器的应用
    • 3.1C++98写法
    • 3.2C++11写法
      • count()的用法
      • 下标运算符operator[ ]
      • lambda表达式的另一种用法
      • C++11写法

C++11包装器_第1张图片

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;
}

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

C++11包装器_第2张图片

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

2.包装器的引入

2.1包装器的定义

#include
// 类模板原型如下
template <class T> 
function;

template <class Ret, class... Args>
class function<Ret(Args...)>;
模板参数说明:
Ret: 被调用函数的返回类型
Args…:被调用函数的形参

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;
}

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;
}

C++11包装器_第3张图片

3.包装器的应用

逆波兰表达式求值
C++11包装器_第4张图片
C++11包装器_第5张图片

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();
	}
};

3.2C++11写法

count()的用法

C++11包装器_第6张图片

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

下标运算符operator[ ]

C++11包装器_第7张图片

如果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;
}

C++11包装器_第8张图片

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();
	}
};

你可能感兴趣的:(遣返回家的C家家,c++,开发语言)