当前位置: 首页 > news >正文

c++进阶之----c++11(包装器)

1. <functional> 头文件

<functional> 是C++11标准库中提供的一个头文件,它包含了许多用于处理可调用对象的工具,例如函数包装器、绑定器、函数适配器等。这些工具可以帮助我们更方便地操作函数、lambda表达式、函数对象等。

(1)std::function

std::function 是一个通用的函数包装器,它可以存储、复制和调用任何可调用对象,包括普通函数、lambda表达式、函数对象、绑定表达式等。若 std::function 不含目标,则称它为。调用空 std::function 的目导致抛出 std::bad_function_call 异常。

特点:

  • 类型安全std::function 通过模板参数指定其调用签名,确保类型安全。

  • 通用性:可以包装几乎任何类型的可调用对象。

  • 可复制性:可以像普通对象一样被复制和赋值。

有一点值得注意的是:(结合下述代码理解)

对于 std::function<int(int, int)> 这种形式,它表示 std::function 将包装一个接受两个 int 参数并返回一个 int 的可调用对象。这里的 int(int, int) 是一个函数类型,而不是两个类型。

如果尝试使用 std::function<int, int> 这种形式,编译器会报错,因为它不符合 std::function 模板的预期参数形式。std::function 的模板参数必须是函数类型,而不是两个独立的类型。

 

个人理解就是将两个int类型的参数给包装在一起,之后返回一个Int类型的结果(如有不对欢迎纠正)

(2)代码测试:

#include<iostream>
#include<functional>
using namespace std;

//函数
int f(int a, int b)
{
	return  a + b;
}
//仿函数
struct functor
{
public:
	int operator()(int a, int b)
	{
		return a + b;
	}
};
class Plus
{
public:
	Plus(int n=9)
		:_n(n)
	{}

	static int plusi(int a, int b)
	{
		return a + b;
	}

	double plusd(double a, double b)
	{
		return (a + b) * _n;
	}
private:
	int _n;
};
int main()
{

	// 包装各种可调用对象
	function<int(int, int)> f1 = f;           //包装普通函数指针
	function<int(int, int)> f2 = functor();  //默认构造,包装仿函数
	function<int(int, int)> f3 = [](int a, int b) {return a + b; };//包装lambda表达式

	cout << f1(1, 1) << endl;
	cout << f2(1, 1) << endl;
	cout << f3(1, 1) << endl;

	// 包装静态成员函数
	// 成员函数要指定类域并且前面加&才能获取地址
	function<int(int, int)> f4 =&Plus::plusi;
	cout << f4(1, 1) << endl;

	function<double(Plus*, double, double)> f5 = &Plus::plusd;
	Plus ps;

	//对比一下:
	//Plus ps;  // 创建一个左值对象
    //Plus();    // 创建一个右值临时对象

	cout << f5(&ps, 1.1, 1.1) << endl;

	function<double(Plus&, double, double)> f6 = &Plus::plusd;
	cout << f6(ps, 1.1, 1.1) << endl;

	function<double(Plus&&, double, double)> f7 = &Plus::plusd;
	cout << f7(Plus(), 1.1, 1.1) << endl;



	return 0;
}

2. std::bind

std::bind 是一个函数绑定器,它允许将一个函数和其参数绑定在一起,创建一个新的可调用对象。std::bind 可以将部分参数预设,从而生成一个“部分应用”的函数。

(1)特点

  • 参数绑定:可以将函数的部分参数绑定为固定值,生成一个新的函数。

  • 灵活性:可以绑定普通函数、成员函数、函数对象等。

  • 占位符:使用占位符(如 std::placeholders::_1)可以指定在调用时动态传入的参数位置。

(2)使用场景

  • 预设参数:将部分参数固定,生成新的函数。

  • 成员函数调用:绑定成员函数和对象,生成可调用的函数对象。

  • 回调函数:生成预设参数的回调函数。

(3)代码测试

using placeholders::_1;
using placeholders::_2;
using placeholders::_3;

int sub(int a,int b)
{
	return (a - b) * 10;
}
int subx(int a, int b, int c)
{
	return (a - b - c) * 10;
}
class Plus
{
public:
	static int plusi(int a, int b)
	{
		return a + b;
	}
	double plusd(double a, double b)
	{
		return a + b;
	}
};

int main()
{
	auto sub1 = bind(sub, _1, _2);
	cout << sub1(10, 5)<<endl;          //10对应_1,5对应_2,_1传给a,_2传给b
	// bind 本质返回的一个仿函数对象
	//	// 调整参数顺序(不常用)
	//	// _1代表第一个实参
	//	// _2代表第二个实参
	//	// ...
	//	// 调整参数熟顺序
	auto sub2 = bind(sub, _2, _1);
	cout << sub2(10, 5) << endl;         //5对应_1,10对应_2,_1传给a,_2传给b
	// 调整参数个数
	// 绑死a
	auto sub3 = bind(sub, 100, _1);
	cout << sub3(5) << endl;   //相当于a=100,b=_1=5
	// 绑死b
	auto sub4 = bind(sub, _1, 100);
	cout << sub4(5) << endl;

	// 分别绑死第123个参数
	auto sub5 = bind(subx, 100, _1, _2);
	cout << sub5(5, 1) << endl;
	auto sub6 = bind(subx, _1, 100, _2);
	cout << sub6(5, 1) << endl;
	auto sub7 = bind(subx, _1, _2, 100);
	cout << sub7(5, 1) << endl;

	// 成员函数对象进行绑死,就不需要每次都传递了
	function<double(Plus&&, double, double)> f6 = &Plus::plusd;
	Plus pd;
	cout << f6(move(pd), 1.1, 1.1) << endl;
	cout << f6(Plus(), 1.1, 1.1) << endl;

	// bind一般用于,绑死一些固定参数
	function<double(double, double)> f7 = bind(&Plus::plusd, Plus(), _1, _2);
	cout << f7(1.1, 1.1) << endl;

	return 0;
}

3.应用

计算复利

 在经济学中利率的计算可以经常用到bind,具体请见下述示例

using placeholders::_1;
int main()
{
	auto func1 = [](double rate, double money, int year)->double {
		double ret = money;
		for (int i = 0; i < year; i++)
		{
			ret += ret * rate;
		}
		return ret - money;
	};
	cout << func1(0.1, 1000000, 30) << endl;
	// 绑死一些参数,实现出支持不同年华利率,不同金额和不同年份计算出复利的结算利息
	function<double(double)> func3_1_5 = bind(func1, 0.015, _1, 3);
	function<double(double)> func5_2_5 = bind(func1, 0.025, _1, 5);
	function<double(double)> func10_3_5 = bind(func1, 0.035, _1, 10);
	function<double(double)> func20_5_5 = bind(func1, 0.055, _1, 20);

	cout << func3_1_5(1000000) << endl;
	cout << func5_2_5(1000000) << endl;
	cout << func10_3_5(1000000) << endl;
	cout << func20_5_5(1000000) << endl;
	return 0;
}


文章转载自:
http://amortisation.alwpc.cn
http://alleynian.alwpc.cn
http://brakeman.alwpc.cn
http://accumulator.alwpc.cn
http://autorotation.alwpc.cn
http://aristocrat.alwpc.cn
http://astrodome.alwpc.cn
http://brae.alwpc.cn
http://amylopsin.alwpc.cn
http://blatant.alwpc.cn
http://brake.alwpc.cn
http://begrudge.alwpc.cn
http://autosemantic.alwpc.cn
http://afraid.alwpc.cn
http://california.alwpc.cn
http://aniconic.alwpc.cn
http://baronetcy.alwpc.cn
http://astyanax.alwpc.cn
http://bioclimatic.alwpc.cn
http://cacophonize.alwpc.cn
http://baseball.alwpc.cn
http://althorn.alwpc.cn
http://chanson.alwpc.cn
http://amphicoelian.alwpc.cn
http://carve.alwpc.cn
http://adolesce.alwpc.cn
http://badian.alwpc.cn
http://bolshy.alwpc.cn
http://chevroler.alwpc.cn
http://carnivalesque.alwpc.cn
http://www.dtcms.com/a/123629.html

相关文章:

  • Elasticsearch 官网阅读学习笔记01
  • SpringBoot 数据库MySql的读写分离 多数据源 Shardingsphere高并发优化
  • go游戏后端开发33:解散房间
  • Vue3+TS——打造AIVista Image Studio的在线生图工具
  • Chrome浏览器和Microsoft Edge浏览器的导出收藏链接
  • JDK 21 的新特性有哪些?带你全面解读 Java 的未来
  • 学习Python的优势体现在哪些方面?
  • ios按键精灵脚本开发游戏辅助工具的代码逻辑
  • QML中的信号与槽机制
  • 2025.04.10-拼多多春招笔试第三题
  • 前端通信库fetch-event-source实现丰富的SSE
  • 【C++经典例题】字符串转整数(atoi)的实现与解析
  • 使用Go语言实现自动清理应用系统日志
  • WP最主题专业的wordpress主题开发
  • 24体育NBA足球直播M24模板自适应板源码
  • Python - 爬虫-网页抓取数据-库requests
  • Docker 是什么? Docker 基本观念介绍与容器和虚拟机的比较
  • 迟滞模式控制的学习
  • 车辆北斗GPS双模定位管理系统 车载定位终端
  • 【学习笔记】CPU 的“超线程”是什么?
  • Opencv计算机视觉编程攻略-第十三节 跟踪视频中的物品
  • 基于 Python 卷积神经网络的新闻文本分类系统,附源码
  • Zookeeper的通知机制是什么?
  • 高并发环境下超发现象的详细分析,包含场景示例、影响分析及解决方案(悲观锁、乐观锁、分布式锁)
  • 实践 DevOps 项目:使用 Terraform、Helm、SonarQube 和 GitLab CI/CD 在 AWS EKS 上实践全栈部署
  • 深入理解 HTML5 Audio:网页音频播放的新时代
  • VMware Workstation/Player 的详细安装使用指南
  • zabbix和prometheus选择那个监控呢
  • 【Vue #2】脚手架 指令
  • 【Java学习】之AI时代下,Java工程师如何修炼