【C++重点语法下】可变参数模板,STL里面的push_back和emplace_back区别 ,包装器function,bind

news2025/1/11 10:54:27

目录

1.可变参数模板

        1.1取出参数包内的参数方法一:

        1.2取出参数包内的参数方法二:  

        1.3STL里面的push_back和emplace_back区别 

2.包装器function

       2.1function(头文件functional)

        2.1.1可调用类型和包装器 

                2.1.2类的成员函数和包装器 

        2.2bind


 

1.可变参数模板

参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。 

//argument翻译:参数
template <class ...Args>
void ShowList(Args... arg)
{
	cout << sizeof...(arg) << endl;
	cout << sizeof...(Args) << endl<< endl;
}
int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', std::string("sort"));

	return 0;
}

使用sizeof需要在(变量)之前加...,即可算出参数包内的个数 

 

1.1取出参数包内的参数方法一:

递归调用 

template<class T,class ...Args>
// 解析并打印参数包中每个参数的类型及值
void ShowList(T val, Args...args)
{
	cout << typeid(T).name() << " " << val << endl;
	ShowList(args...);
}

执行结果:参数包的元素在递归中会被拿完;但是至少应该有一个参数才可以继续递归(参数包的参数可以为0-n),但是T必须有参数实例化;而且没有递归调用结束条件; 

 

// 递归终止函数
template<class T>
void ShowList(T val)
{
	cout << typeid(T). name() << " " << val << endl << endl;
}
template<class T,class ...Args>
 解析并打印参数包中每个参数的类型及值
void ShowList(T val, Args...args)
{
	cout << typeid(T).name() << " " << val << endl;
	ShowList(args...);
}

int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', std::string("sort"));
	return 0;
}

执行结果:

 

1.2取出参数包内的参数方法二:  

    int arr[] = { PrintArg(args)... };很奇怪的语法,只有硬背 

  • { PrintArg(args)... };把这个展开;有几个参数就展开几个,比如参数包内有3个参数,int arr[]={PrintArg(args),PrintArg(args),PrintArg(args)};
template <class T>
int PrintArg(T val)
{
	T copy(val);
	cout << typeid(T).name() << ":" << val << endl;
}

//展开函数
template <class ...Args>
void ShowList(Args... args)
{
	int arr[] = { PrintArg(args)... };
	cout << endl;
}
int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', std::string("sort"));
	return 0;
}

执行结果:

1.3STL里面的push_back和emplace_back区别 

  • push_back是左值和右值的引用;emplace_back是万能引用
  • emplace_back使用的是参数包
  • 右值:emplace_back是:直接使用参数构造;push_back是使用参数先构造临时对象,在再资源转移
  • 左值:都是直接使用左值拷贝构造
  • emplace_back在右值比push_back效率高一点点;优化了但是只能优化一点点;

 

2.包装器function

ret = func(x);

上面func可能是什么呢?那么func可能是函数名?函数指针?函数对象(仿函数对象)?也有可能是lamber表达式对象?

  • 例lambda表达是:auto fun=[](int a,int b)->int{return a+b;};
template<class F, class T>
void useF(F f, T x)
{
	static int count = 0;
	cout << "count:" << ++count << endl;
	cout << "count:" << &count << endl;
}
//普通函数
double f(double i)
{
	return i / 2;
}

struct Functor
{
	double operator()(double d)
	{
		return d / 3;
	}
};
int main()
{
	// 函数名
	useF(f, 11.11);
	// 函数对象
	useF(Functor(), 11.11);
	// lamber表达式
	useF([](double d)->double { return d / 4; }, 11.11);
	return 0;
}

执行结果:static修饰的局部变量声明周期变长,如果实例化的是一份;应该是1,2,3;且地址不同说明不是一个;

 

结论:将实例化出3份,效率低,有没有办法实例化一份就好

先看下面,懂了再来看这几句代码

	std::function<double(double)> func1 = f;
	useF(func1, 11.11);
	// 函数对象
	std::function<double(double)> func2 = Functor();
	useF(func2, 11.11);
	// lamber表达式
	std::function<double(double)> func3 = [](double d)->double { return d /4; };
	useF(func3, 11.11);

 2.1function(头文件functional)

 

2.1.1可调用类型和包装器 

#include <functional>
int f(int a, int b)
{
	return a + b;
}
struct Functor
{
public:
	int operator() (int a, int b)
	{
		return a + b;
	}
};

int main()
{
	// 函数名(函数指针)
	std::function<int(int, int)> func1 = f;
	cout << func1(1, 2) << endl;
	// 函数对象/仿函数
	std::function<int(int, int)> func2 = Functor();
	cout << func2(1, 2) << endl;
	// lamber表达式
	std::function<int(int, int)> func3 = [](const int a, const int b)
	{return a + b; };
	cout << func3(1, 2) << endl;

	return 0;
}

执行结果: 

2.1.2类的成员函数和包装器 

 类的成员函数和包装器 

class Plus
{
public:
	static int plusi(int a, int b)
	{
		return a + b;
	}
	double plusd(double a, double b)
	{
		return a + b;
	}
};
int main()
{
	// 类的成员函数
	std::function<int(int, int)> func4 = &Plus::plusi;
	cout << func4(1, 2) << endl;
	std::function<double(Plus, double, double)> func5 = &Plus::plusd;
	cout << func5(Plus(), 1.1, 2.2) << endl;
	return 0;
}

 

  1. std::function<int(int, int)> func4 = &Plus::plusi; 静态成员函数可以省略&取地址符号(推荐不省略以免搞混);因为静态成员函数可以使用:类名::静态成员函数使用
  2. std::function<double(Plus, double, double)> func5 = &Plus::plusd;普通成员函数不可以使用类名::静态成员函数名类使用;必须要有一个对象来访问,&取地址符号也不可以省略;所以多了一个参数;绑定可以解决多一个参数的问题

 2.2bind

bind是一个函数模板,它就像一个函数包装器(适配器),接受一个可调用对象(callable object),生成一个新的可调用对象来“适应”原对象的参数列表

  1. 通过bind调整参数顺序
  2. 通过bind调整参数个数

通过bind调整参数顺序 

int SubFunc(int x, int y)
{
	return x - y;
}
int main()
{
	function<int(int, int)> func1 = SubFunc;
	cout << func1(10, 5) << endl;
	//没有改变参数顺序
	function<int(int, int)> func2 = bind(SubFunc, placeholders::_1, placeholders::_2);
	cout << func2(10, 5) << endl;
	//交换参数顺序
	function<int(int, int)> func3 = bind(SubFunc, placeholders::_2, placeholders::_1);
	cout << func3(10, 5) << endl;
	return 0;
}

  

 通过bind调整参数个数

class Add
{
public:
	int add(int x, int y)
	{
		return x + y;
	}
};
int main()
{
	//需要对象来调用普通函数
	function<int(Add, int, int)> func4 = &Add::add;
	cout << "func4:" << func4(Add(), 10, 20) << endl;
	//使用bind改变参数个数
	function<int(int, int)> func5 = bind(&Add::add,Add(), placeholders::_1, placeholders::_2);
	cout << "func5:" << func5(10, 20) << endl;
	return 0;
}

 

可以使用auto接受,但是function的参数很明确; 

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

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

相关文章

实验十 符号计算基础与符号微积分(matlab)

目录 实验十 符号计算基础与符号微积分 1.1实验目的 1.3流程图 1.4程序清单 1.5运行结果及分析 1.6实验的收获与体会 1.1实验目的 1.2实验内容 符号计算基础与符号微积分 课本第372页 1.3流程图 1.4程序清单 实验十 1 clear xsym(6); ysym(5); z(1x)/(sqrt(…

第9章 登录页面的跳转实现

1 “swg-login.html”登录按钮不能触发异常 由于.Net框架默认支持“HTTPS”协议从而导致“swg-login.html”登录按钮不能触发&#xff0c;其异常信息如下&#xff1a;“Mixed Content: The page at https://localhost:7037/swg-login.html was loaded over HTTPS, but requeste…

FinalShell软件连接成功后,root文件夹显示一直加载中....

出现这样的问题就是因为我们一开始进入的用户是普通用户&#xff0c;然后你就会想着使用su命令转为超级用户&#xff0c;但是这样式不可行的&#xff0c;因为虚拟机会默认你第一次进入的用户是当前用户&#xff0c;还是解决不了问题。 解决办法&#xff1a; 再开一个连接进入…

java基于springboot_vue的校园闲置物品交易系统-计算机毕业设计

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven 本文从管理员、用户的功能要求…

Java(八)----多线程(二)

1. 生产者与消费者 1.1 安全问题产生 线程本身就是一个新创建的方法栈内存 (CPU进来读取数据) 线程的notify(),唤醒第一个等待的线程 解决办法 : 全部唤醒 notifyAll() 被唤醒线程,已经进行过if判断,一旦醒来继续执行 线程被唤醒后,不能立刻就执行,再次判断标志位,利用循环 …

[附源码]Python计算机毕业设计Django基于Vue的社区拼购商城

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Python学习日记-第三十八天-生成器

系列文章目录 生成器创建生成器的方法生成器-使用send方式唤醒使用yield完成多任务一、生成器 利用迭代器&#xff0c;我们可以在每次迭代获取数据&#xff08;通过next方法&#xff09;时按照特定的规律进行生成&#xff0c;但是我们在实现一个迭代器时&#xff0c;关于当前…

Pr:导出设置之基本视频设置

视频 VIDEO设置因所选导出格式而异。每种格式都有独特的要求&#xff0c;这些要求决定了哪些设置可用。以导出文件格式为 H.264 为例&#xff0c;下面给出有关基本视频设置 Basic Video Settings的选项及说明。匹配源Match Souce自动设定视频设置选项以匹配源视频的属性。支持匹…

项目一共30个模块,你叫我maven版本一个个手动改?

之前有个群友私聊问我&#xff0c;如何快速统一去更改项目中所有的maven版本号&#xff0c;他说之前都是手动一个个去修改&#xff0c;项目一共有30多个maven模块&#xff0c;上次因为漏改了一个&#xff0c;还造成了生产事故。 其实我自己开源项目有的工程也非常多&#xff0…

Java入门必备知识你能掌握多少?

1、Java是一种高级计算机语言&#xff0c;是可以编写跨平台应用软件、完全面向对象的程序设计语言。 2、Java划分为三个技术平台&#xff1a;Java SE、Java EE、Java ME Java SE是桌面应用&#xff0c;Java EE是web应用&#xff0c;平台企业版&#xff0c;Java ME是手机应用&…

亚马逊鲲鹏系统批量注册功能可以让你快速拥有大量亚马逊买家号

亚马逊鲲鹏系统是一款能批量注册买家号、AI智能一键养号、模拟真人行为轨迹进行刷单测评的软件&#xff0c;而对于批量注册买家号&#xff0c;操作也是比较简单的。 主要流程是购买了相应的账号所需资料后&#xff0c;通过批量导入邮箱、邮箱密码、信用卡、收货地址进入软件然后…

嵌入式分享合集114

一、DMA DMA&#xff0c;全称Direct Memory Access&#xff0c;即直接存储器访问。 DMA传输将数据从一个地址空间复制到另一个地址空间&#xff0c;提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。 我们知道CPU有转移数据、计算、控制程序转移等很多功能&…

拿到8000元的火焰杯比赛奖金,感谢霍格沃兹测试开发学社

下面是我们获奖学员自己主动分享的 然后发给霍格沃兹测试开发学社表示感谢的&#xff0c;收到她的反馈我们也由衷的开心。所以也分享给大家&#xff0c;目前无论是应届生 在校生还是从业人员&#xff0c;都可以加入第三届火焰杯比赛&#xff0c;赢取属于专属于自己的荣耀。 我…

学生HTML个人网页作业作品:基于HTML实现教育培训机构网站模板毕业源码(8页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

[附源码]JAVA毕业设计霍山石斛网站(系统+LW)

[附源码]JAVA毕业设计霍山石斛网站&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…

AutoJs7打包薅羊毛时间版

AutoJs7打包薅羊毛时间版 一、准备工作&#xff1a; autojs7 app 下载地址&#xff1a;Auto.js Pro7.apk - 蓝奏云薅羊毛时间版 下载地址&#xff1a; 亚丁号---文件下载 安卓手机一部外加数据线&#xff08; Type-C或者USB&#xff09;&#xff0c;最好是安卓7的系统。电脑…

云服务器购买流程

云服务器购买流程 在技术学习的路上&#xff0c;除了虚拟机外最贴近实战的机器就是服务器。实际上在企业中有些小企业用的也是租赁的云服务器&#xff0c;有些是自己公司搭建的服务器。不管什么服务器了&#xff0c;实际上都是一样的&#xff0c;如果想更靠近企业级开发&#x…

Kotlin高仿微信-第52篇-搜索好友

Kotlin高仿微信-项目实践58篇详细讲解了各个功能点&#xff0c;包括&#xff1a;注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…

HTTP

文章目录一、HTTP 基本概念GET 与 POSTHTTP 特性HTTP 与 HTTPSHTTP/1.1、HTTP/2、HTTP/3 演变HTTP/1.1如何优化如何避免发送 HTTP 请求&#xff1f;如何减少 HTTP 请求次数减少重定向请求次数合并请求延迟发送请求如何减少 HTTP 响应的数据⼤⼩&#xff1f;⽆损压缩有损压缩HTT…

YGG 和 BlockchainSpace 举办全国最大的 Web3 活动:Philippine Web3 Festival

2022 年 11 月 14 日至 18 日&#xff0c;Yield Guild Games (YGG) 和 BlockchainSpace 在菲律宾共同举办了迄今为止最大的 web3 活动&#xff0c;汇集了来自世界各地的游戏玩家、建设者、投资者、开发者、教育工作者和艺术家加入 web3 的应用。该活动吸引了来自 web3 社区的数…