C++高级开发之可调用对象、function、bind(2)

简介: std::bind 绑定器  要使用这个函数模板,在 cpp文件前面要包含如下头文件#include<funcitonal>  std::bind能够将对象以及相关的参数绑定到一起,绑定完成后可以直接调用,也可以用

C++高级开发之可调用对象、function、bind(1):https://developer.aliyun.com/article/1415893

std::bind 绑定器

  要使用这个函数模板,在 cpp文件前面要包含如下头文件#include

  std::bind能够将对象以及相关的参数绑定到一起,绑定完成后可以直接调用,也可以用

std::function进行保存,在需要的时候调用。该函数模板的一般使用格式如下:


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

std::bind有两个意思:

  • 将可调用对象和参数绑定到一起,构成一个仿函数,所以可以直接调用
  • 如果函数有多个参数,可以绑定部分参数,其他的参数在调用的时候指定
      具体演示:在main函数中加入如下代码:
  void myfunc1(int x, int y, int z)
{
  cout << "x=" << x << ",y=" << y << ",z=" << z << endl;
}


在主函数中,加入如下代码

//表示绑定函数myfunc1的第一,二,三个参数值为:10 20 30,返回值auto表示我们不关心它返回的是啥类型,
//实际它返回的也是个仿函数类型对象,可以直接调用,也可以赋给std::function
  auto bf1 = std::bind(myfunc1, 10, 20, 30);
  bf1();

48497b6ec7e74a4a902acdb64f184902.png

上述范例非常简单,在 std::bind中,就可以直接给 myfunc1指定各参数。

  具体演示2:

//表示绑定函数myfunc1的第三个参数为30,而myfunc1的第一,二个参数分别由调用bf2时的第一,二个参数指定, _1、_2...、_20这种是标准库里定义的,占位符的含义,类似这样的参数有20个,
//够我们用了,这里这个placeholders::_1表示这个位置(当前该placeholders::_1所在的位置)将在函数调用时,被传入的第一个参数所代替。
  auto bf2 = std::bind(myfunc1, placeholders::_1, placeholders::_2, 30);
  bf2(5, 15);


81f7a71d3ff34f3c850d5bb2e6250d38.png

直接调用也可以

  std::bind(myfunc1, placeholders::_1, placeholders::_2,30)(10, 20);

03859f8d6d0f4a9b8b3b224135822c2e.png

再看一例:

在 cpp文件前面增加 myfun2函数的定义。

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

在main函数中加入如下代码。注释很关键

    int a = 2;
    int b = 3;
    auto bf4 = std::bind(myfunc2, a, placeholders::_1);
    bf4(b); //执行后a=2,b=4。这说明:bind对于预先绑定的函数参数是通过值传递的,所以这个a实际上是值传递的。
        //bind对于不事先绑定的参数,通过std::placeholders传递的参数是通过引用传递的,所以这个b实际上是引用传递的
    cout << "a: "<<a<<"b:"<<b << endl;

34592bc0682f46c79f871f8009797449.png

在看一例:

在 cpp文件中增加 CQ类定义

class CQ
{
public:
  CQ()
  {
    printf("CQ::CQ()构造函数执行,this=%p\n", this);
  }
  CQ(const CQ&)
  {
    printf("CQ::CQ(const CQ&)拷贝构造函数执行,this=%p\n", this);
  }
  ~CQ()
  {
    printf("CQ::~CQ()析构函数执行,this=%p\n", this);
  }
public:
  void myfunpt(int x, int y)
  {
    cout << "x=" << x << ",y=" << y << endl;
    m_a = x;
  }
  int m_a = 0; //成员变量
};

在main函数中,加入如下代码:

  CQ cq; //一个类对象
  auto bf5 = std::bind(&CQ::myfunpt, cq, placeholders::_1, placeholders::_2); //类函数有绝对地址,和对象无关,但要被调用必须有类对象参数
  bf5(10, 20);//对成员函数的调用

9d9c68b0089f4d17a0e00dbe569a1d34.png

注意上面代码中,std::bind的第二个参数 cq会导致生成一个临时的 CQ对象std::bind是将该临时对象和相关的成员函数以及多个参数绑定到一其,后续对 myfunpt成员函数的调用修改的是这个临时的 CQ对象的额m_a,并不影响真实的 cq对象的 m_a值。

 如果将 std::bind的第二个参数 cq前面增加 &,这样就不会导致生成一个临时的CQ对象,后续的修改就是直接对cq对象的修改了。

在main函数中继续计入代码,观察 bind和 function的配合使用

  //bind 和 function配合使用(bind返回值直接赋给 std::function类型)
  CQ cq;
  std::function<void(int, int)> bfc6 = std::bind(&CQ::myfunpt, cq, std::placeholders::_1, std::placeholders::_2);
  bfc6(10, 20);

dd5a751db14b4abb826481340d1e0933.png

 cq->bind->function(构造->拷贝->拷贝)

加入饮用之后能够明显看到效率的提高

08274ce70c344862861728bd3202f34b.png

总结

 因为有了占位符,所以 std::bind的使用就变得非常灵活。可以直接绑定函数的所有参数,也可以使用 std::placeholders来决定bind所在位置的参数将会属于调用发生时的第几个参数。


std::bind 的思想实际上是一种延迟计算的思想,将可调用对象保存起来,然后后在需要的时候在调用。

  • std::function 一般要绑定一个可调用对象,类成员函数不能被绑定。而 std::bind更加强大,成员函数、成员变量等都能绑定。现在通过 std::function和std::bind的配合,所有的可调用对象都有了统一的操作方法。
目录
相关文章
|
2天前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
35 18
|
3月前
|
编译器 C++
C++之类与对象(完结撒花篇)(上)
C++之类与对象(完结撒花篇)(上)
45 0
|
2天前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
30 13
|
9天前
|
IDE 开发工具 C语言
C++一分钟之-嵌入式编程与裸机开发
通过这些内容的详细介绍和实例解析,希望能帮助您深入理解C++在嵌入式编程与裸机开发中的应用,提高开发效率和代码质量。
30 13
|
2月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
121 5
|
2月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
125 4
|
2月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
172 4
WK
|
2月前
|
机器学习/深度学习 人工智能 算法
那C++适合开发哪些项目
C++ 是一种功能强大、应用广泛的编程语言,适合开发多种类型的项目。它在游戏开发、操作系统、嵌入式系统、科学计算、金融、图形图像处理、数据库管理、网络通信、人工智能、虚拟现实、航空航天等领域都有广泛应用。C++ 以其高性能、内存管理和跨平台兼容性等优势,成为众多开发者的选择。
WK
120 1
|
3月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
37 4
|
3月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
38 4