C++11 -- 包装器

news2024/12/26 11:40:53

文章目录

  • function包装器
    • function包装器的概念
    • function的运用
    • function实例化
    • 使用function解决逆波兰表达式
  • bind包装器
    • bind包装器相关介绍
    • bind绑定函数固定参数

function包装器

function包装器的概念

function包装器,也叫做适配器,它的本质是一个类模板.
例如:

1 template< class R, class... Args >
2 class function< R (Args...)>

说明
( 1 ) :R是被调用函数的返回类型 Args…是被调用的函数的形参,本质上是一个参数包.

( 2 ): function是类模板,只有成员函数,没有数据成员。

function的运用

function包装器可以对普通函数,函数对象,lambda表达式,类中的成员函数进行包装,以下针对各类函数进行包装调用以及相关注意事项如下:

double f(double a, double b)
{
	return a + b;
}
struct Functor
{
public:
	int operator()(int a, int b)
	{
		return a + b;
	}
};
class Plus
{
public:
	static int Plusi(int a, int b)         //静态成员函数
	{
		return a + b;
	}
	double Plusd(double a, double b)      //成员函数
	{
		return a + b;
	}
};
int main()
{
	//包装函数指针
	function<double(double, double)> funcf = f;  //传递函数名
	cout << funcf(1.1, 2.2) << endl;

	//包装仿函数
	function<int(int, int)> funcFunctor = Functor();//传递仿函数对象
	cout << funcFunctor(11, 22) << endl;

	//包装lambda表达式
	function<int(int, int)> funcLmd = [](int a, int b) {return a + b;}; //传递匿名对象
	cout << funcLmd(11, 22) << endl;

	//静态成员函数
	function<int(int, int)> funcPlusi = Plus::Plusi;  //标明类域,传递函数名.
	cout << funcPlusi(11, 22) << endl;

	//非静态成员函数
	function<double(Plus, double, double)> funcPlusd = &Plus::Plusd; //增加&,标明类域,传递函数名.

	cout << funcPlusd(Plus(),3.3,4.4)<< endl;        //因为类的成员函数需要对象的调用,所以必须传递额外传递一个对象.                        
	return 0;
}

function实例化

包装器可以解决模板实例化多份而造成的效率低下的问题.
例如:

  • 在useF模板中,有两个参数,第一个参数可以接收各种函数类型,第二个参数可以接收各种信息.
  • useF函数模板中的定义了一个静态变量,如果实例化出多分useF函数模板,静态变量count也将不是同一个变量.

代码如下:

template<class F, class T>
T useF(F f, T x)
{
	static int count = 0;
	cout << "count: " << ++count << endl;

	cout << "count: " << &count << endl;
	return f(x);
}
double f(double i)
{
	return i / 2;
}
struct Functor
{
	double operator()(double d)
	{
		return d / 3;
	}
};
int main()
{
	//函数指针
	cout << useF(f, 11.11) << endl;

	//仿函数
	cout << useF(Functor(), 11.11) << endl;

	//lambda表达式
	cout << useF([](double d)->double {return d / 4; }, 11.11) << endl;
	return 0;
}

运行结果如下:

  • 由此可见,在这里由于我们对useF函数模板的第一个参数T传递了三种不同类型的函数,进而导致useF函数模板在编译阶段实例化出了三份,因为静态变量为三个不同的变量.
  • 在使用三种不同函数作为实参传递并调用useF函数模板,实际上是分别调用了一次不同的useF函数,进而导致useF函数中的静态变量不是同一个,所以count只增加了一次.
  • 但是由于我们所传的三种函数类型的返回值数据类型和形参数据类型是一样的,在执行useF函数中,其他数据类型也相同,所以根本就没必要实例化三份useF函数.
    在这里插入图片描述
    所以,包装器可以解决因为该情况而导致模板实例化多份造成效率低下的问题.
int main()
{
	//函数名
	function<double(double)> func1 = func;
	cout << useF(func1, 11.11) << endl;

	//函数对象
	function<double(double)> func2 = Functor();
	cout << useF(func2, 11.11) << endl;

	//lambda表达式
	function<double(double)> func3 = [](double d)->double {return d / 4; };
	cout << useF(func3, 11.11) << endl;
	return 0;
}


运行效果如下:

  • 由于useF类模板中的静态变量相同,由此可以判断经过function包装过后,useF函数模板只实例化出了一份,这极大地提高了函数模板的效率.
  • 当我们传递三种不同的函数类型并进行调用时,实际上就是调用了三次同一个useF函数,对静态变量count累加了三次.
    在这里插入图片描述

使用function解决逆波兰表达式

bind包装器

bind的本质是一个函数模板,它就像一个函数包装器(适配器),可以接收一个可调用对象的,从而生成一个新的可调用对象来"适应"原对象的参数列表.

bind包装器相关介绍

bind原型如下:

// 原型如下:
template <class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
// with return type (2) 
template <class Ret, class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);

注意:
( 1 ): fn 指的是需要包装的对象.

( 2 ): args…对应的是给定fn函数中的参数.

调用bind的一般形式如下:

auto newCallable = bind(callable,arg_list);

( 1 ) callable: 需要包装的对象…

( 2 ) newCallable: 生成的一个新的可调用对象.

( 3 ) arg_list: arg_list是一个逗号分隔的参数列表,对应给定的callable的参数.当我们调用newCallable时,newCallable会调用callable,并将arg_list参数列表传给callable中.

注意:
arg_list中的参数可能包含形如_n的名字,其中n是一个整数,这些参数是“占位符”,表示newCallable的参数,它们占据了传递给newCallable的参数的“位置”。例如: _1为newCallable的第一个参数,_2为第二个参数,以此类推.

bind绑定函数固定参数

为什么要使用bind绑定固定参数呢?

因为使用bind绑定固定参数后,可以通过bind包装后生成新的形参较少的对象来调用原来的对象.

例如:
在以下例子中,对于成员函数来说,要通过bind包装新生成的对象调用,因为成员函数需要对象才能调用,所以我们要比全局成员函数要额外多传递一个参数,但是当我们使用包装器bind同时包装全局成员函数和普通成员函数时,那么包装器此时根本无法判断接收参数的具体个数.
在这里插入图片描述
代码如下:

int Plus(int a, int b)
{
	return a / b;
}

}
class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};
int main()
{
	function< int(int, int)> funcPlus = Plus;

	function< int(int, int)>funcSub = bind(&Sub::sub, Sub(), _1, _2);

	map<string, function<int(int, int)>> funcMap =
	{

		{"+",Plus},
		{"-",bind(&Sub::sub,Sub(),_1,_2) }
	};

	cout << funcSub(2, 1) << endl;
	
	cout << funcMap["-"](2, 1) << endl;
}
  • 将成员函中要接收三个参数经过bind适配器绑定后,在定义时只需要在&Sub::sub后面直接传递的一个sub()匿名对象进行该参数绑定,然后在以后的调用时,只需要传递对应的函数所需要的形参就可以了.
  • 这样也完美的解决了bind同时包装类的成员函数和全局函数接收参数不匹配的问题.
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/591536.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python中的迭代器

Python中的迭代器 在Python中&#xff0c;迭代器是一种对象&#xff0c;它可以让我们可以遍历&#xff08;或迭代&#xff09;序列中的元素而不必了解它们如何存储在内存中。迭代器是Python中许多高级构造的基础 - 他们节省了空间&#xff0c;并且它们能够帮助我们更有效地处理…

Redis高级篇 - 多级缓存

多级缓存 1.什么是多级缓存 传统的缓存策略一般是请求到达Tomcat后&#xff0c;先查询Redis&#xff0c;如果未命中则查询数据库&#xff0c;如图&#xff1a; 存在下面的问题&#xff1a; 请求要经过Tomcat处理&#xff0c;Tomcat的性能成为整个系统的瓶颈 Redis缓存失效时…

VUE项目运行失败原因以及解决办法(以vscode为例)

1.正常运行&#xff1a; Ctl J打开终端&#xff0c;并运行如下命令&#xff1a; npm run serve 正常情况下&#xff0c;就可以得到本地和网络链接&#xff0c;如下&#xff1a; 点击链接即可进入到编辑好的页面。 不过&#xff0c;你也可能遇到如下情况↓↓↓ 2.无法找到pac…

创建第一个.NET MAUI应用

1.打开VS2022,创建新项目,并选择.NET MAUI应用,然后点击下一步 2.输入项目相关配置,然后点击下一步 3. 选择框架版本,然后点击创建 4.项目创建成功后会自动打开概述页 5.平台框架切换 6.启动应用,如有下图提示,启动开发者模式 成功启动应用 7.修改应用 修改MainPage.xml如下图…

Baumer工业相机堡盟工业相机如何使用CameraExplorer软件设置MultiROI模式以及该模式的优势以及行业应用

Baumer工业相机堡盟工业相机如何使用MultiROI模式以及该模式的优势以及行业应用 Baumer工业相机Baumer工业相机的MultiROI模式的技术背景Baumer工业相机使用CameraExplorer软件设置MultiROI模式1.开启Baumer工业相机MultiROI模式2.关闭Baumer工业相机MultiROI模式3.测试使用Bau…

C++ 排序算法

&#x1f914;排序算法&#xff1a; &#x1f4d6;1.sort 对容器内元素进行排序 &#x1f4d6;2.random_shuffle 洗牌 指定范围内的元素随机调整次序 &#x1f4d6;3.merge 容器元素合并&#xff0c;并整合到另一个容器中 &#x1f4d6;4.reverse 反转指定容…

强推宝藏网站

最近还是有很强烈的感受&#xff0c;方法大于努力。最近就整理了一下大学期间比较好用的网站&#xff0c;也陪我度过了一段时间了&#xff0c;排名不分先后&#xff0c;把压箱底的东西拿出来了。 ChatGPT WeTab 新标签页https://www.wetab.link/ChatGPT国内免费使用方法有哪些…

【数据结构6】二叉树的基本操作

文章目录 ⭐️写在前面的话⭐️二叉树的一些基本操作1、结构定义2、先序创建这棵树3、按满二叉树方式创建4、三种递归遍历5、层次遍历6、求二叉树的深度7、求叶子结点数8、三种非递归遍历9、先序线索化二叉树10、先序线索化后遍历11、中序线索化二叉树12、中序线索化后遍历主函…

MySQL进阶- SQL优化和视图

目录 SQL优化插入数据时的SQL优化&#xff08;insert优化&#xff0c;和大批量数据插入&#xff09;主键优化order by优化&#xff08;排序操作的优化&#xff09;group by优化&#xff08;分组优化&#xff09;limit优化&#xff08;分页查询优化&#xff09; SQL优化 插入数…

[RUST/腐蚀]Windows-开服服务端下载以及配置

一、前置要求 1.SteamCMD&#xff1a;SteamCMD - Valve Developer Communityhttps://developer.valvesoftware.com/wiki/SteamCMD 2.通过SteamCMD下载RUST/腐蚀服务端。 二、SteamCMD 注意&#xff1a;所有目录均应避免出现中文。 1.建立SteamCMD文件夹&#xff0c;如 D:\st…

准备入门python的一些建议

提醒&#xff1a;一下内容只代表个人观点 从18年左右开始&#xff0c;python的广告就被打得满天飞&#xff0c;网上各种吹嘘python这门语言的广告五花八门&#xff0c;当然也有一些人看完这些广告后感觉python非常的高大上&#xff0c;然后就入门学习了python&#xff0c;我就…

【测试基础02】

测试基础02 一、HTML基础二、Python导入三方模块三、安装webgrock驱动四、元素定位(1)、元素定位工具(2)、元素定位方式(3)、XPATH路径(3)、CSS选择器 五、Selenium WebDriver初步应用(1)、基本方法(2)、测试案例1(3)、测试案例2(3)、测试案例3 六、获取元素信息的方法七、fram…

价值5000元以上的某马大数据全套视频【强烈推荐】

某马大数据 01、阶段一 Python大数据开发基础 01、第一章大数据介绍及开发环境 02、第二章 linux命令 03、第三章 MySQL数据库 04、第四章 excel的使用 05、第五章 kettle的使用 06、第六章 数据分析及可视化 07、第七章 大数据框架与数仓基础 08、第八章 数仓实战项目 …

3-网络初识——协议

目录 1.概念 ①语法&#xff1a;即数据与控制信息的结构或格式。 ②语义&#xff1a;即需要发出何种控制信息&#xff0c;完成何种动作以及做出何种响应。 ③时序&#xff1a;即事件实现顺序的详细说明。 2.作用 3.知名协议的默认端口 4.协议分层 4.1.什么是协议分层 …

chatgpt赋能python:Python中的转置操作:理解与实践

Python中的转置操作&#xff1a;理解与实践 在Python中&#xff0c;可以使用转置操作来将矩阵或数组的行和列交换位置。转置操作不仅在数学和统计学上有广泛应用&#xff0c;也在机器学习和数据分析领域中非常重要。在本文中&#xff0c;我们将深入探讨Python中的转置操作的基…

C# | 使用Memory<T>高效地读写内存数据

C# | 使用Memory高效地读写内存数据 文章目录 C# | 使用Memory<T>高效地读写内存数据前言Memory<T>介绍示例结束语 前言 Memory<T>是C# 7.2版本中引入的一种新类型&#xff0c;可以更加高效地读写内存数据。本文将介绍它的用途以及如何使用它来优化代码。 P…

机器视觉康耐视智能相机Insight-手眼标定详细步骤

(Q有答疑)康耐视VisionPro工具与脚本入门级系列教程2023 In-Sight 智能相机包含标定手眼的工具 CalibrateGrid,用手动的标定方式,即将康耐视标定片固定在运动平台上,然后手动输入电机位置坐标,要保证电机在 X 方向移动一次,Y 方向移动一次,旋转两次角度,切旋转角度差不能…

chatgpt赋能python:Python中的绝对值函数

Python中的绝对值函数 在Python编程语言中&#xff0c;绝对值函数是一个非常重要和常用的函数。它可以帮助我们快速地计算一个数的绝对值&#xff0c;而不需要手动使用if语句来处理。在本文中&#xff0c;我们将介绍Python中的绝对值函数&#xff0c;并且讨论它的一些应用。 …

Linux 上安装 PostgreSQL——Ubuntu

打开 PostgreSQL 官网 PostgreSQL: The worlds most advanced open source database&#xff0c;点击菜单栏上的 Download &#xff0c;可以看到这里包含了很多平台的安装包&#xff0c;包括 Linux、Windows、Mac OS等 。 Linux 我们可以看到支持 Ubuntu 和 Red Hat 等各个平台…

ARC学习(1)基本编程模型认识

笔者有幸接触了arc处理器&#xff0c;今天就来简单了解一下arc的编程模型 1、ARC基本认识 ARC IP是synopsys 新思公司开发的一个系列ARC IP核&#xff0c;其是一家电子设计自动化&#xff08;EDA&#xff09;解决方案提供商。其主页地址在这里&#xff01;业务主要如下&#x…