C++ | std::bind

本文介绍了C++中的std::bind函数,包括其函数原型、参数和返回对象的类型。通过实例展示了如何绑定普通函数、类成员函数、模板函数以及使用lambda表达式。还提供了绑定成员变量和静态成员函数的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++ | std::bind

std::bind函数原型

// 无返回值(1)
template <class Fn, class... Args>  /* unspecified */ bind (Fn&& fn, Args&&... args);
// 有返回值(2)
template <class Ret, class Fn, class... Args>  /* unspecified */ bind (Fn&& fn, Args&&... args);

bind函数参数

fn 为绑定的函数对象,比如函数对象、函数指针、函数引用、成员函数或者数据成员函数。

args 为函数的入参列表,使用命名空间占位符std::placeholders::_1(第1个参数),std::placeholders::_2(第2个参数)等标志参数。

每个参数可以绑定到一个值或者是一个占位符:

  • 如果绑定到一个值,调用返回的函数对象将始终使用该值作为参数。
  • 如果是占位符,则调用返回的函数对象会将传递给调用的参数转发给调用(其顺序号由占位符指定的参数)。

调用返回的对象返回与 fn 相同的类型,除非将特定的返回类型指定为 Ret (2)(请注意,Ret 是唯一不能通过传递给此函数的参数隐式推导的模板参数)。

返回对象的类型:

返回一个函数对象,它的返回值与 fn 相同的结果,其参数也绑定到 args…(或转发,用于占位符)。
对如果f是指向类的成员函数,则返回函数第一个参数应该是该类的成员、或者成员对象的引用、或者是成员对象的指针。

实战

1.普通函数/类成员函数/类成员变量

#include <functional>  // std::bind
#include <iostream>    // std::cout

// a function: (also works with function object: std::divides<double>
// randy_divide;)
double randy_divide(double x, double y) { return x / y; }

struct RandyPair {
  double randy, sesame;
  double multiply() { return randy * sesame; }
  static double Add(double lhs, double rhs) {
    return lhs + rhs;
  }
};

int main() {
  using namespace std::placeholders;  // adds visibility of _1, _2, _3,...

  // binding functions:
  auto fn_five = std::bind(randy_divide, 10, 2);  // returns 10/2
  std::cout << fn_five() << '\n';                 // 5

  auto fn_half = std::bind(randy_divide, _1, 2);  // returns x/2
  std::cout << fn_half(22) << '\n';               // 11

  auto fn_invert = std::bind(randy_divide, _2, _1);  // returns y/x
  std::cout << fn_invert(10, 2) << '\n';             // 0.2

  auto fn_rounding = std::bind<int>(randy_divide, _1, _2);  // returns int(x/y)
  std::cout << fn_rounding(9, 3) << '\n';                   // 3

  RandyPair three_eleven{3, 11};

  // binding members:
  auto bound_member_fn =
      std::bind(&RandyPair::multiply, _1);             // returns x.multiply()
  std::cout << bound_member_fn(three_eleven) << '\n';  // 33

  auto bound_member_data =
      std::bind(&RandyPair::randy, three_eleven);  // returns ten_two.a
  std::cout << bound_member_data() << '\n';        // 3
    
   // function pointer
   RandyPair *pRandyPairPtr = new RandyPair();
  pRandyPairPtr->randy = 3.0;
  pRandyPairPtr->sesame = 8.0;
  auto bindFuncPtr = std::bind(&RandyPair::multiply, pRandyPairPtr);
  std::cout << "bindFuncPtr(): " << bindFuncPtr() << '\n'; 

   auto bindClassStaticFunc = std::bind(&RandyPair::Add, _1, _2);
  std::cout << "bindClassStaticFunc(2, 13): " << bindClassStaticFunc(2, 13) << '\n'; 
    
  return 0;
}

结果:

5
11
0.2
3
33
3
bindFuncPtr(): 24
bindClassStaticFunc(2, 13): 15

2.模板函数

#include <functional>  // std::bind
#include <iostream>    // std::cout

template <class T>
void TemplateBindFunc(T lhs, T rhs)
{
    std::cout << "模板函数被调用, lhs = " << lhs << ", rhs = " << rhs << std::endl;
}


int main() {
  using namespace std::placeholders;  // adds visibility of _1, _2, _3,...

  auto templateFunc = std::bind(&TemplateBindFunc<int>, _1, _2);
  templateFunc(2, 13);
  return 0;
}

结果:

模板函数被调用, lhs = 2, rhs = 13

3.lambda表达式

#include <functional>  // std::bind
#include <iostream>    // std::cout

int main() {
  auto lamdaFunc = std::bind(
      [](int randy, int sesame "") {
        std::cout << "lambda表达式, randy = " << randy << ", sesame = " << sesame << std::endl;
      },
      std::placeholders::_1, std::placeholders::_2);
  lamdaFunc(1, 22);
  
  return 0;
}

结果:

lambda表达式, randy = 1, sesame = 22

Reference


欢迎关注公众号【三戒纪元】

### C++ 中 `std::function` 和 `std::bind` 的用法及区别 #### 定义与基本概念 `std::function` 是一种通用多态函数封装器,可以存储任何可调用对象(如普通函数、lambda 表达式、绑定表达式或其他函数对象)。其灵活性使得它能够作为回调机制的一部分,在事件驱动编程和其他场景下非常有用。 ```cpp #include <functional> #include <iostream> void simpleFunction(int a) { std::cout << "Value is: " << a << '\n'; } int main() { // 创建一个 std::function 对象并赋值给简单函数 std::function<void(int)> f = simpleFunction; f(42); } ``` 另一方面,`std::bind` 提供了一种方式来创建新的可调用对象,这些新对象可以通过固定某些参数或将多个可调用实体组合在一起的方式简化现有可调用目标的接口。通过 bind 可以提前设置部分参数,从而减少后续调用时传递相同参数的需求[^1]。 ```cpp #include <functional> #include <iostream> class MyClass { public: void memberFunc(int i, double d) const { std::cout << "Integer value: " << i << ", Double Value:" << d << "\n"; } }; int main(){ using namespace std::placeholders; MyClass obj; // 绑定成员函数到特定实例,并预先设定第一个参数 auto boundMember = std::bind(&MyClass::memberFunc, &obj, _1, 3.14); // 调用已绑定的对象只需要提供剩余未固定的参数即可 boundMember(7); } ``` #### 主要差异点 - **目的不同**: `std::function` 更侧重于作为一个容器去保存各种类型的可调用对象;而 `std::bind` 则专注于调整已有可调用对象的行为模式,比如预设一些输入参数。 - **使用场合的区别**: 当需要定义一个能接受多种不同类型但签名兼容的函数指针的地方时,应该优先考虑使用 `std::function`; 如果想要改变某个具体函数或方法的工作方式,则可以选择 `std::bind`. - **性能考量**: 在大多数情况下,直接使用 lambda 表达式可能比使用 `std::bind` 效率更高,因为后者可能会引入额外的小型分配开销以及间接层。然而对于复杂情况下的参数绑定操作来说,`std::bind` 还是有它的优势所在[^2].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值