【深入理解C++】可调用对象、std::function、std::bind()

news2025/2/23 18:44:35

文章目录

  • 1.可调用对象
    • 1.1 函数指针
    • 1.2 具有operator()成员函数的类对象/仿函数/函数对象
    • 1.3 可被转换为函数指针的类对象
    • 1.4 类成员函数指针
  • 2.std::function
    • 2.1 绑定普通函数
    • 2.2 绑定类的静态成员函数
    • 2.3 绑定具有operator()成员函数的类对象
    • 2.4 绑定可被转换为函数指针的类对象
  • 3.std::bind()
    • 3.1 绑定普通函数
    • 3.2 绑定类的成员函数
    • 3.3 绑定具有operator()成员函数的类对象
    • 3.4 bind() 和 function 配合使用

1.可调用对象

1.1 函数指针

#include <iostream>
using namespace std;

void fun(int v)
{
	cout << "fun()函数执行了,v = " << v << endl;
}

int main()
{
	void(*pfun)(int) = fun;
	pfun(15);

	return 0;
}

1.2 具有operator()成员函数的类对象/仿函数/函数对象

#include <iostream>
using namespace std;

class TC
{
public:
	void operator()(int tv) // 函数调用运算符
	{
		cout << "TC::operator()执行了,tv = " << tv << endl;
	}
};

int main()
{
	TC tc;
	tc(20); // 等价于tc.operator()(20);

	return 0;
}

1.3 可被转换为函数指针的类对象

#include <iostream>
using namespace std;

class TC
{
public:
	using pfun = void(*)(int); // 使用using指定别名

	static void fun(int tv) // 静态成员函数
	{
		cout << "TC::fun()静态成员函数执行了,tv = " << tv << endl;
	}

	operator pfun() // 类型转换运算符,能把本类类型对象转换成一个函数指针
	{
		return fun;
	}
};

int main()
{
	TC tc;
	tc(50); // 等价于tc.operator TC::pfun()(50);

	return 0;
}

1.4 类成员函数指针

#include <iostream>
using namespace std;

class TC
{
public:
	void fun(int tv)
	{
		cout << "TC::fun()执行了,tv = " << tv << endl;
	}
};

int main()
{
	TC tc;
	void(TC::*pfun)(int) = &TC::fun; // 类成员函数指针变量pfun的定义与初始化
	(tc.*pfun)(50); // 通过对象tc调用成员函数fun

	return 0;
}

2.std::function

头文件为 #include <functional>

std::function,即可调用对象包装器,它是个类模板,通过给它指定模板参数,它就能够用统一的方式来处理各种可调用对象(类成员函数指针除外)。

2.1 绑定普通函数

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

void fun(int v)
{
	cout << "fun()函数执行了,v = " << v << endl;
}

int main()
{
	std::function<void(int)> f1 = fun;
	f1(100);

	return 0;
}

2.2 绑定类的静态成员函数

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

class TC
{
public:
	static int fun(int tv) // 静态成员函数
	{
		cout << "TC::fun()静态成员函数执行了,tv = " << tv << endl;
		return tv;
	}
};

int main()
{
	std::function<int(int)> f2 = TC::fun;
	cout << f2(100) << endl;

	return 0;
}

2.3 绑定具有operator()成员函数的类对象

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

class TC
{
public:
	void operator()(int tv) // 函数调用运算符
	{
		cout << "TC::operator()执行了,tv = " << tv << endl;
	}
};

int main()
{
	TC tc;
	std::function<void(int)> f3 = tc;
	f3(100);

	return 0;
}

2.4 绑定可被转换为函数指针的类对象

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

class TC
{
public:
	using pfun = void(*)(int); // 使用using指定别名

	static void fun(int tv) // 静态成员函数
	{
		cout << "TC::fun()静态成员函数执行了,tv = " << tv << endl;
	}

	operator pfun() // 类型转换运算符,能把本类类型对象转换成一个函数指针
	{
		return fun;
	}
};

int main()
{
	TC tc;
	std::function<void(int)> f4 = tc;
	f4(100);

	return 0;
}

3.std::bind()

头文件:#include <functional>

格式:std::bind(待绑定的函数指针/成员函数指针/函数对象, 绑定参数值1, ..., 绑定参数值n);

std::bind() 返回的是仿函数类型对象。

3.1 绑定普通函数

将可调用对象和参数绑定到一起,构成一个仿函数,所以可以直接调用。

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

void fun(int x, int y, int z)
{
	cout << "x = " << x << ", y = " << y << ", z = " << z << endl;
}

int main()
{
	auto bf = std::bind(fun, 10, 20, 30);
	bf();

	return 0;
}

如果函数有多个参数,可以绑定部分参数,其他的参数在调用的时候指定。

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

void fun(int x, int y, int z)
{
	cout << "x = " << x << ", y = " << y << ", z = " << z << endl;
}

int main()
{
	auto bf = std::bind(fun, placeholders::_1, 20, placeholders::_2);
	bf(10, 30);

	return 0;
}

在这里插入图片描述

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

void fun(int x, int y, int z)
{
	cout << "x = " << x << ", y = " << y << ", z = " << z << endl;
}

int main()
{
	std::bind(fun, placeholders::_1, 20, placeholders::_1)(10, 30);

	return 0;
}

在这里插入图片描述

std::bind() 对于预先绑定的函数参数是通过值传递的,对于通过 placeholders 占位的参数是通过引用传递的。

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

void fun(int& x, int& y)
{
	x++;
	y++;
}

int main()
{
	int a = 2;
	int b = 3;
	
	auto bf = std::bind(fun, a, placeholders::_1);
	bf(b);

	cout << "a = " << a << ", b = " << b << endl;

	return 0;
}

在这里插入图片描述

3.2 绑定类的成员函数

在下面代码中,CQ 类本身不是仿函数,第二个参数 cq 会导致调用 CQ 类的拷贝构造函数生成一个 CQ 类型的临时对象作为 std::bind() 的返回值。

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

class CQ
{
public:
	CQ()
	{
		cout << "构造函数 - " << this << endl;
	}
	CQ(const CQ&)
	{
		cout << "拷贝构造函数 - " << this << endl;
	}
	~CQ()
	{
		cout << "析构函数 - " << this << endl;
	}
	void fun(int x, int y)
	{
		cout << "x = " << x << ", y = " << y << endl;
	}
};

int main()
{
	CQ cq;
	auto bf = std::bind(&CQ::fun, cq, std::placeholders::_1, std::placeholders::_2);
	bf(10, 30);

	return 0;
}

在这里插入图片描述

在下面代码中,CQ 类本身不是仿函数,第二个参数是 &cq,这样就不生成 CQ 类型的临时对象了,此时 std::bind() 返回的就是 cq 对象本身。

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

class CQ
{
public:
	CQ()
	{
		cout << "构造函数 - " << this << endl;
	}
	CQ(const CQ&)
	{
		cout << "拷贝构造函数 - " << this << endl;
	}
	~CQ()
	{
		cout << "析构函数 - " << this << endl;
	}
	void fun(int x, int y)
	{
		cout << "x = " << x << ", y = " << y << endl;
	}
};

int main()
{
	CQ cq;
	auto bf = std::bind(&CQ::fun, &cq, std::placeholders::_1, std::placeholders::_2);
	bf(10, 30);

	return 0;
}

在这里插入图片描述

3.3 绑定具有operator()成员函数的类对象

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

class CQ
{
public:
	CQ()
	{
		cout << "构造函数 - " << this << endl;
	}
	CQ(const CQ&)
	{
		cout << "拷贝构造函数 - " << this << endl;
	}
	~CQ()
	{
		cout << "析构函数 - " << this << endl;
	}
	void operator()()
	{
		cout << "operator() - " << this << endl;
	}
};

int main()
{
	auto bf = std::bind(CQ());
	bf();

	return 0;
}

在这里插入图片描述

3.4 bind() 和 function 配合使用

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

class CQ
{
public:
	CQ()
	{
		cout << "构造函数 - " << this << endl;
	}
	CQ(const CQ&)
	{
		cout << "拷贝构造函数 - " << this << endl;
	}
	~CQ()
	{
		cout << "析构函数 - " << this << endl;
	}
	void fun(int x, int y)
	{
		cout << "x = " << x << ", y = " << y << endl;
	}
};

int main()
{
	CQ cq;
	std::function<void(int, int)> bf = std::bind(&CQ::fun, cq, std::placeholders::_1, std::placeholders::_2);
	bf(10, 30);

	return 0;
}

在这里插入图片描述

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

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

相关文章

【无标题】SAR雷达系统反设计及典型目标建模与仿真实现研究——目标生成与检测(Matlab代码实现)

&#x1f352;&#x1f352;&#x1f352;欢迎关注&#x1f308;&#x1f308;&#x1f308; &#x1f4dd;个人主页&#xff1a;我爱Matlab &#x1f44d;点赞➕评论➕收藏 养成习惯&#xff08;一键三连&#xff09;&#x1f33b;&#x1f33b;&#x1f33b; &#x1f34c;希…

408考研科目《数据结构》第八章第一节:排序的基本概念和插入排序(直接插入排序,折半插入排序,希尔排序)

文章目录教程1.排序的基本概念1.1 排序算法的评价指标1.2 排序算法的分类2. 插入排序2.1 直接插入排序2.1.1 算法效率分析2.2 折半插入排序总结2.3 希尔排序 &#xff08;Shell Sort&#xff09;总结教程 排序&#xff1a; https://www.bilibili.com/video/BV1b7411N798/?p77…

队列——算法专项刷题(七)

七、队列 常用于辅助遍历树&#xff0c;设计队列先进先出特性的数据结构 7.1 滑动窗口的平均值 给定一个整数数据流和一个窗口大小&#xff0c;根据该滑动窗口的大小&#xff0c;计算滑动窗口里所有数字的平均值。 实现 MovingAverage 类&#xff1a; MovingAverage(int si…

图书管理系(附源码PPT)

图书管理系统1 绪 论1.1 研究背景1.2 研究意义1.3 相关研究现状1.3.1 高校图书管理面临的问题1.3.2 信息化为图书管理带来新变化2 相关技术2.1 JSP 概述2.2 MySQL 数据库技术2.3 Spring2.4 SpringMVC2.5 Dbcp2.6 Maven3 系统分析3.1 需求分析3.1.1 系统的功能需求分析3.1.2 系统…

利用衍射表面消色差的混合目镜建模

1. 摘要 同时具有折射和衍射表面的混合透镜已成为一种极具潜力的解决方案应用于多种领域。在此案例中&#xff0c;我们将演示混合目镜的一个例子&#xff0c;其中利用衍射透镜表面对色差进行了校正。由ZemaxOpticStudio进行初始化设计&#xff0c;并导入VirtualLab Fusion进行进…

TensorRt(2)快速入门介绍

文章目录1、使用ONNX部署的示例1.1、导出模型1.2、设置batch size批处理大小1.3、指定数值精度1.4、转换模型1.5、部署模型2、使用ONNX转换为engine再部署的示例2.1、导出ONNX模型2.1.1、从TensorFlow中导出ONNX2.1.1、从PyTorch中导出ONNX2.2、ONNX 转化为 TensorRT Engine2.3…

27个超实用Chrome控制台调试技巧 Source 全局搜索(关注更新)

谷歌开发者工具提供了一系列的功能来帮助开发者高效 Debug 网页应用&#xff0c;让他们可以更快地查找和修复 bug。在谷歌的开发者工具中&#xff0c;有非常多有用的小工具&#xff0c;但是很多开发者并不知道。通过这篇文章&#xff0c;我把我常用的那些高效 Debug 的 Chrome …

ARM 汇编指令集1_2

一、两个概念&#xff1a;指令与伪指令 &#xff08;汇编&#xff09;指令&#xff0c;是 CPU 机器指令的助记符&#xff0c;经过编译后会得到一串10组成的机器码&#xff0c;可以由 CPU 读取执行。&#xff08;汇编&#xff09;伪指令&#xff0c;本质上不是指令&#xff08;…

版本控制利器——changelog

问题描述 当前&#xff0c;我们项目需要进行版本的确定&#xff0c;人工审核代码已接近尾声&#xff0c;但为了防止后续继续出现该问题&#xff0c;我希望能够做到在每次push到master时&#xff0c;更新changelog 将每一个版本的commit记录下来&#xff0c;类似于下列 解决…

K8s 集成 Jenkins 部署Go Web项目

风离不摆烂学习日志 Day9 K8s 集成 Jenkins 部署Go Web项目 Dockerfile FROM golang:alpine as builder # 需要go环境 MAINTAINER fl1906WORKDIR /work # 源 RUN go env -w GOPROXYhttps://goproxy.cn && go env -w CGO_ENABLED0 && go env -w GO111MODULEon C…

Splunk UBA 从 Ldap 成功导入 HR 数据

1: 今天在配置Splunk UBA 的HRdata 和asset data 的时候,都要用到ldap, 所以还非要装add-on:\ add-on 的名字: Splunk Supporting Add-on for Active Directory (SA-LDAPSearch) (SA-LDAPSearch) 这个add-on 的配置: Configure the Splunk Supporting Add-on for Activ…

使用腾讯云cos搭建图片服务器

背景 当我们能不希望把图片上传到自己的服务器时&#xff0c;可以采用腾讯云cos帮我们免费代图片&#xff0c;我们只需要在自己的数据库里保存一个图片地址就行了 二、注册账号免费试用 1、注册腾讯云账号 按照腾讯云的注册方式&#xff0c;注册自己的账号 2、实名认证 选择个…

blender boxCutter插件

boxCutter可以用来进行bool运算 打开boxCutter 方法1&#xff1a;物体模式在舞台左侧选择boxCutter图标 方法2&#xff1a;物体模式按N&#xff0c;在舞台右侧的侧边栏里选择boxCutter 方法3 物体模式alta 打开BoxCutter后&#xff0c;舞台上方&#xff0c;N键的弹出菜单&…

进行 Spring 6 迁移的最佳方式

介绍 在本文中&#xff0c;我们将了解如何将现有应用程序迁移到Spring 6以及如何充分利用此升级。 本文中的提示基于我在Hypersistence Optimizer和高性能 Java Persistence 项目中添加对 Spring 6 的支持所做的工作。 爪哇 17 首先&#xff0c;Spring 6 将最低 Java 版本提…

2022.11.27 学习周报

文章目录摘要文献阅读1.题目2.摘要3.介绍4.基于后向传播算法的多时间尺度RNN4.1 循环神经网络&#xff08;RNN&#xff09;4.2 基于多时间尺度的RNN预测模型5.实验5.1 数据简介5.2 数据分析5.3 评价指标5.4 实验结果6.结论深度学习1.循环神经网络&#xff08;RNN&#xff09;1.…

Flutter 5 大本地数据库解决方案

Flutter 5 大本地数据库解决方案 原文 https://levelup.gitconnected.com/top-5-local-database-solutions-for-flutter-development-6351cd494070 前言 这里列出了最流行的数据库解决方案以及代码示例。 选择正确的数据管理系统对于提高效率和可 extension 性以及影响可用性和…

3DConvCaps:3DUNet与卷积胶囊编码器用于医学图像分割

摘要 卷积神经网络需要大量的训练数据&#xff0c;无法处理物体的姿态和变形。此外其中的池化层也倾向于丢弃位置等重要的信息。CNN对旋转和仿射变换非常敏感。 胶囊网络是最近出现的一种新型体系结构&#xff0c;其通过动态路由和卷积步长代替池化层&#xff0c;在部分整体表…

steam搬砖项目的核心内容解答

大家好&#xff0c;我是阿阳 如果你有个几千块钱积蓄&#xff0c;想做点小生意&#xff0c;又不知道做啥&#xff0c;那我建议你来做steam搬砖&#xff0c;steam搬砖是什么呢&#xff1f;steam搬砖怎么赚钱的呢&#xff1f;你听我一步步跟你说来 steam搬砖是什么呢&#xff1f…

详解GMM高斯混合模型EM模型

一般讲到GMM就会讲到EM。 我不过多的介绍EM算法。这里只是举一些例子来看看真实的GMM怎么用EM算的。 一、GMM的作用 记住GMM的作用&#xff0c;就是聚类&#xff01; 二、GMM有hard和soft两种 hard-GMM和soft-GMM是为了对标k-means和soft k-means。在中文互联网上搜索到的GM…

【SVM分类】基于matlab哈里斯鹰算法优化支持向量机SVM分类【含Matlab源码 2243期】

⛄一、哈里斯鹰算法简介 HHO算法用数学公式来模拟现实中哈里斯鹰在不同机制下捕捉猎物的策略.在HHO中&#xff0c;哈里斯鹰是候选解&#xff0c;猎物随迭代逼近最优解.HHO算法包括两个阶段&#xff1a;全局探索阶段、局部开采阶段。 1 全局探索阶段 在这一阶段中&#xff0c;哈…