std::bind的讲解

std::bind std::bind是函数模板(是一个函数); 使用std::bind可以将可调用对象和参数一起绑定,绑定后的结果使用std::function进行保存,并延迟调用到任何我们需要的时候。 std::bind返回一个基于f的函数对象,其参数被绑定到args上。 f的参数要么被绑定到值,要么被绑定到placeholders(占位符,如_1, _2, ..., _n)。 即;可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。 std: 阅读详情

一、在讲解std::bind之前,我们先来复习下std::function。

std::function 是一个“可调用对象”包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。

什么是可调用对象?

(1)函数指针
(2)具有operator()成员函数的类对象(传说中的仿函数),lambda表达式
(3)可被转换为函数指针的类对象
(4)类成员(函数)指针
(5)bind表达式或其它函数对象

比如:

// 普通函数
int add(int a, int b){return a+b;} 

// lambda表达式
auto mod = [](int a, int b){ return a % b;}

// 函数对象类
struct divide{
    int operator()(int denominator, int divisor){
        return denominator/divisor;
    }
};

用std::function将上述类型保存起来:

std::function<int(int ,int)>  a = add; 
std::function<int(int ,int)>  b = mod ; 
std::function<int(int ,int)>  c = divide(); 

二、std::bind

可将std::bind函数看作一个通用的函数适配器,它接受一个“可调用对象”,生成一个新的可调用对象来“适应”原对象的参数列表。

std::bind主要有以下两个作用:
(1)将可调用对象和其参数绑定成一个防函数;
(2)只绑定部分参数,减少可调用对象传入的参数。

1、绑定普通函数

double divide (double x, double y) {
    return x/y;
}

auto divide_half = std::bind (my_divide,_1,2);  
std::cout << fn_half(10) << std::endl; // 输出5

(1)bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind (divide,_1,2)等价于std::bind (&divide,_1,2);
(2)_1表示占位符,位于<functional>中,std::placeholders::_1;

2、绑定成员函数

#include <functional>
#include <iostream>

using namespace std;

struct Foo {
    void sum(int n1, int n2)
    {
        std::cout << n1+n2 << std::endl;
    }

	static int StaticMember(int a) { 
        return 66 + a; 
    }

    int data = 10;
};

int main() {
    Foo foo;
    auto f = std::bind(&Foo::sum, &foo, 95, std::placeholders::_1);
    f(5); // 输出100
}

(1)bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。
(2)必须显示的指定&Foo::sum,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在Foo::sum前添加&;
(3)使用对象成员函数的指针时,必须要知道该指针属于哪个对象,因此第二个参数为对象的地址 &foo;

3、绑定静态成员函数

	auto fun2 = &Foo::StaticMember;
    cout<<fun2(3)<<endl;

4、绑定成员变量

#include <functional>
#include <iostream>

using namespace std;

class TestClass4 {
public:
    TestClass4() : m_a(100)
    {}
	
public:
    int m_a;
};

int main() {
    TestClass4 test4;
    auto fun4 = std::bind(&TestClass4::m_a, std::placeholders::_1);

	int var = fun4(test4);
    std::cout<<var<<std::endl;
}

5、绑定仿函数

#include <functional>
#include <iostream>

using namespace std;

class TestClass5 {
public:
    TestClass5() = default;
	
    TestClass5(const TestClass5& obj) {
        std::cout<<"TestClass5 copy construct."<<std::endl;
    }
	
    void operator()(int a) {
        std::cout<<a<<std::endl;
    }
};

int main(){
    TestClass5 test5;
    auto fun5 = test5;
    fun5(2018);
}

6、绑定成员函数时,哪些做法会先调用“拷贝构造函数” ?

#include <functional>
#include <iostream>

using namespace std;

class TestClass {
public:
    TestClass(int a):m_a(a){}
    TestClass(const TestClass& obj) {
        m_a = obj.m_a + 100;
        std::cout<<"copy construct."<<std::endl;
    }
	
    int ClassMember(int a) {
	    std::cout<<" this:"<<this<<" :"<<&m_a<<" "<<m_a<<std::endl;
		return 55 + a; 
	}
	
    int ClassMember2(int a,char ch,float f) {
        std::cout <<ch <<" "<< f << " "<<a<<std::endl;
        return 55 + a;
    }
	
    static int StaticMember(int a) {
	    return 66 + a; 
	}

public:
    int m_a;
};;

int main(){
    TestClass test(67);
    std::cout<<"&test "<<&test<<" "<<test.m_a<<" &test.m_a "<<&test.m_a<<std::endl;
    std::cout<<"---------------------------------------------------------------------"<<std::endl;
	auto fun4 = std::bind(&TestClass::ClassMember, test, std::placeholders::_1); // 调用拷贝构造函数
	fun4(4);
	
	std::cout<<"---------------------------------------------------------------------"<<std::endl;
	auto fun5 = std::bind(&TestClass::ClassMember, &test, std::placeholders::_1); // 不调用拷贝构造函数
    fun5(5);
	
	std::cout<<"---------------------------------------------------------------------"<<std::endl;
	auto fun6 = &TestClass::StaticMember; // 不调用拷贝构造函数
    std::cout<<fun6(6)<<std::endl;
	
	std::cout<<"---------------------------------------------------------------------"<<std::endl;
    auto fun7 = std::bind(&TestClass::m_a, std::placeholders::_1); // 不调用拷贝构造函数
    std::cout<<fun7(test)<<" "<<test.m_a<<std::endl;
	
}

执行结果:

7、传引用参数的问题

当需要把对象传到bind中的参数中时,需要使用ref或者cref。

#include<iostream>
#include<functional>
 
using namespace std;
using namespace placeholders;
 
void alter(int &a, int b) {
    a = b;
}

int main() {
    int a = 5;
    auto f1 = bind(alter, a, _1);      //此处bind中的参数a只是a的一个拷贝,而不是a的引用
    f1(9);                           
    cout << a << endl;                //所以此处a仍为5
 
    auto f2 = bind(alter, ref(a), _1);  //使用ref可以将a的引用传递给bind
    f2(9);
    cout << a << endl;                //所以此处a变成了9
 
    return 0;
}
 
 

8、指向成员函数的指针

#include <iostream>
struct Foo {
    int value;
    void f1() { std::cout << "f1(" << this->value << ")\n"; }
    void f2() { std::cout << "f2(" << this->value << ")\n"; }
};

void apply(Foo* foo1, Foo* foo2, void (Foo::*fun)()) {
    (foo1->*fun)();  // call fun on the object foo1
    (foo2->*fun)();  // call fun on the object foo2
}

int main() {
    Foo foo1{1};
    Foo foo2{2};

    apply(&foo1, &foo2, &Foo::f1);
    apply(&foo1, &foo2, &Foo::f2);
}

(1)成员函数指针的定义:void (Foo::*fun)(),调用时传递的实参: &Foo::f;

(2)fun为类成员函数指针,所以调用时要通过解引用的方式获取成员函数*fun,即(foo1->*fun)()。

参考:

(1)C++11 中的std::function和std::bind

(2)c++bind函数使用

(3)第六节 std::bind 绑定器

(4)c++11随记:std::bind及 std::placeholders

std::bind()函数详解 阅读详情

相关推荐

std::bind源码剖析

bind实际上用途极为广泛,特别是在多线程的程序中,经常用它将函数进行包装,然后打包发送给工作线程,让工作线程去执行我们的任务。

飞鸟的专栏 5416

C++11中的std::bind 简单易懂

概述 std::bind的头文件是 <functional>,它是一个函数适配器,接受一个可调用对象(callable object),生成一个新的可调用对象来“适应”原对象的参数列表。 函数原型 std::bind函数有两种函数原型,定义如下: template< class F, class... Args > /*unspecified*/ bind( F&& f, Args&&... args ); template< clas.

姜的理想国 7万+

C++中的std::bind

std::bind是 C++11 引入的一个强大的工具,能够将函数或成员函数与固定的参数绑定,创建一个新的可调用对象。它支持占位符_2等,用于表示参数的位置。可以用来绑定普通函数、成员函数,甚至是自定义的函数对象。尽管std::bind功能强大,但在某些情况下,Lambda 表达式可能是更直观和高效的选择。std::bind是一个非常有用的函数适配工具,尤其在回调机制、异步编程、以及 STL 算法中都有广泛的应用。

m0_49476241的博客 907

C++中的std::bind深入剖析

std::bind在 C++11 中引入,提供了一种将可调用对象(如函数、成员函数、函数对象等)与参数进行绑定的方式。然而,随着 C++ 的发展,尤其是 C++11 之后的版本,std::bind的使用逐渐受到了一些限制,因为 lambda 表达式提供了更加灵活和直观的方式来实现类似的功能。以下是std::bind优点:灵活性std::bind可以绑定函数、成员函数、函数对象等的参数,提供了一种灵活的方式来创建新的可调用对象。与结合使用std::bind创建的可调用对象可以很容易地赋值给。

红军不怕远征难,万水千山只等闲 7295

你知道C++11中std::function和std::bind用法吗?

目录 ​​​​​​​1. 可调用对象 2. std::function 3. std::bind 3.1 std::bind绑定普通函数 3.2 std::bind绑定一个成员函数 3.3 绑定一个引用参数 4. 指向成员函数的指针 1. 可调用对象 可调用对象有一下几种定义: 是一个函数指针,参考 C++ 函数指针和函数类型; 是一个具有operator()成员函数的类的对象; 可被转换成函数指针的类对象; 一个类成员函数指针; C++中可调用对象的虽然都有一个比较统一的操作形式

啊渊的专栏 970

C++11 中的std::function和std::bind

1. 可调用对象 可调用对象有一下几种定义: 是一个函数指针,参考 C++ 函数指针和函数类型; 是一个具有operator()成员函数的类的对象; 可被转换成函数指针的类对象; 一个类成员函数指针; C++中可调用对象的虽然都有一个比较统一的操作形式,但是定义方法五花八门,这样就导致使用统一的方式保存可调用对象或者传递可调用对象时,会十分繁琐。C++11中提供了std::function和st...

波风水门 774

【C++学习(28)】通俗一点讲解:std::bind 回调技术

std::bind允许你预先设置函数的某些参数,从而得到一个新的函数(或可调用对象),这个新的函数只需要你提供剩下的参数。这在回调函数和异步编程中特别有用,因为你可能希望预先决定某些参数的值,而让其他参数在稍后的某个时间点被提供。

AbiUni(YY熊) 389

TensorRT(C++)部署 Pytorch模型

众所周知,python训练pytorch模型得到.pt模型。但在实际项目应用中,特别是嵌入式端部署时,受限于语言、硬件算力等因素,往往需要优化部署,而tensorRT是最常用的一种方式。本文以yolov5的部署为例,说明模型部署在x86架构上的电脑端的流程。(部署在Arm架构的嵌入式端的流程类似)。

女神sha手的博客 5404

chatgpt真好用——std::bind和std::function

下面回归正题,就是为何使用std::bind生成一个可调用的对象,叫做callable object。已经如何使用std::bind绑定类的成员函数。我们将类Person的Add函数,对象p,以及参数3和一个占位参数std::placeholders::_2绑定成一个对象func。chatgpt是一本正经的回答,有时候也是一本正经的胡说八道,不过挺有意思的。然后后面在合适的适合调用。

小孔明的专栏 333

开关电源|控制方式PWM、PFM、混合调制

频率调制器根据误差放大器的输出大小来改变方波信号的频率,若负载电流突然增加,输出电压 Vout随之下降,反馈电压 VFB 减小,此时误 差放大器的输出增高,频率调制器输出方波信号的频率增大,增加电感充电次数;若负载电流突然增加,输出电压Vom随之下降,反馈电压Vr减小,此时误差放大器的输出增高,PWM比较器输出方波信号的占空比增大,增加电感充电时间:若负载电流突然下降,PWM比较器输出方波信号的占空比减小,减少电感充电时间,从而稳定输出电压。它是在固定开关频率下,通过改变脉冲宽度来调节占空比的。

weixin_46969363的博客 1万+

深入解析SDC时钟约束:从create_clock到set_clock_groups的实战指南

本文深入解析SDC时钟约束,从create_clock到set_clock_groups的实战应用,帮助数字芯片设计工程师掌握时序约束的核心技巧。通过详细讲解时钟三要素(波形定义、不确定性和时钟关系)及实战案例,提升时钟约束的精准性和效率,避免常见设计陷阱。

weixin_29274337的博客 1078

C++学习:std::function与std::bind

在C++工程实践中,bind绑定器和function函数对象非常的重要,依靠他们可以便捷的实现松耦合。

菜一头包的博客 1427

LIGGGHTS颗粒模拟入门:从DEM原理到工程实践

离散元法(DEM)是一种用于模拟颗粒物质行为的数值方法,其核心原理是通过计算每个颗粒的运动和相互作用来预测颗粒系统的宏观行为。该方法基于牛顿第二定律和接触力学模型,能够精确描述颗粒间的碰撞、摩擦和粘结等微观机制。在工程实践中,DEM技术为优化工业设备设计、预测材料流动和减少实验成本提供了重要价值。它广泛应用于制药造粒、矿石破碎、粉体输送和农业加工等领域,帮助工程师和研究人员深入理解颗粒系统的复杂动力学。LIGGGHTS作为一款基于LAMMPS的开源DEM软件,继承了其高效的并行计算架构,并针对颗粒模拟进行了

weixin_33979203的博客 419

C++11中的std::bind

文章转载自:http://www.jellythink.com/archives/773 看看这段代码 这几天学习Cocos2d-x,看到了以下的一段代码: // new callbacks based on C++11 #define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__) #define CC_CALLBACK_1(__selector

danshiming的博客 267

「Unity3D」Addressable版本冲突解析:SBP与Addressables兼容性问题实战指南

本文深入解析Unity3D中Addressable与SBP(Scriptable Build Pipeline)版本冲突问题,提供实战解决方案。当遇到「Build Task CreateBuiltInShadersBundle failed」错误时,可通过版本匹配、临时资源引用或构建参数调整解决。文章详细分析兼容性原理,并给出版本组合指南与最佳实践,帮助开发者高效处理资源构建问题。

weixin_29001683的博客 410

置顶必读(2) | 《YOLOv11实战:从入门到深度优化》目录导航篇(持续更新中)

🏆 本文收录于 《YOLOv11实战:从入门到深度优化》 专栏。 本专栏系统梳理并持续复现全网各类 YOLOv11 / YOLO系列改进方案与实战案例,目前已覆盖 分类、检测、分割、追踪、关键点、OBB 检测 等多个方向。 内容坚持 持续更新 + 深度拆解 + 工程落地导向,不仅讲“怎么改”,更讲“为什么这样改、如何真正落地到项目中”。

**My Coding Family** 11万+

std::bind()之std::placeholders理解记录

使用 std::bind() 需要添加 #include<functional> 头文件 std::bind()函数接受一个可调用对象及其参数(如果有的话),形成一个新的可调用对象。 可调用对象:普通函数体,Lambda表达式(匿名函数),类成员函数,静态成员函数,仿函数(重载了括号运算符的类)等都可以称为可调用对象。 void TestFunc(int a, char b, float c) { cout << a << endl; cout <&lt

maybcsdn的博客 4503

ISMN数据处理

可批量下载,十分方便

m0_46268055的博客 1216

C++中的std::function和std::bind

C++中的std::function和std::bind 1.可调用对象 可调用对象有以下几种: 一个函数指针; 一个具有operator()成员函数的类对象; 可被转换成函数指针的类对象; 一个类成员函数指针 C++中可调用对象虽然都有一个比较统一的操作形式,但定义方法五花八门,导致使用统一的方式保存可调用对象或者传递可调用对象时,会十分繁琐。C++11中提供了std::function和std::bind统一可调用对象的各种操作。 不同类型可能具有相同的调用形式,如: 上述三种可调用对象虽然类型不

y小川的专栏 476

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

std::bind()与std::ref()

文章目录1.std::bind()1. 前言2. std::bind()的作用3.placeholders的作用4.std::bind()使用测试4.1 固定参数、调换顺序4.2 普通函数的参数中有引用类型4.3 普通函数嵌套包装5.包装类成员5.1 成员变量的包装6.总结2.std::ref和std::cref1.为什么需要std::ref和std::cref1.2运行结果:1.3结果分析3.std::ref()和&1.探究过程2.结论 1.std::bind() 1. 前言 不知道大家在做项目写

Destiny_的博客 1810

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

【C++11】C++11 std::function, std::bind, std::ref, std::cref

【C++11】C++11 std::function, std::bind, std::ref, std::cref std::function 看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed; std::function<void(EventKeyboard::KeyCode, Event*)> onKeyReleased; 这两行代码是从Cocos2d-x中

qq_43331089的博客 333

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

C++之std::bind()函数的使用

C++ std::bind()函数的使用

qq_44237695的博客 5778

std::bind实验

std::bind实验

322

C++11 之 std::function、std::bind、std::placeholders

在公司说的项目代码中看到了std::function、std::bind、std::placeholders三个C++11的特性,通过了解之后,发现还是挺有用的,在这里记录下吧。似乎这三个特性一般都是一起使用的,所以也一起讲了。 三个特性都在functional文件中定义,故使用时需要“#include<functional>” 1.基础介绍 这里...

u014209688的专栏 5508
上一篇: std::function的讲解与实战
下一篇: C++线程池(1)理论基础及简单实现
老蔡编程
博客等级 码龄23年 48粉丝 75原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值