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

发布于:2024-04-26 ⋅ 阅读:(24) ⋅ 点赞:(0)

C++语言中有几种可调用对象:函数、函数指针、lambda 表达式、bind 创建的对象以及重载了函数调用运算符的类。

和其他对象一样,可调用对象也有类型。两个不同类型的可调用对象可能共享同一种调用形式(call signature)。调用形式指明了调用返回的类型以及传递给调用的实参类型。一种调用形式对应一个函数类型,例如:int (int, int) 是一个函数类型,它接受两个int,返回一个int。

// 普通函数
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;
  }
};
上面这些可调用对象分别对其参数执行了不同的算术运算,尽管它们的类型各不相同,但是共享同一种调用形式:
int(int ,int)

C++中可调用对象虽然都有一个比较统一的操作形式,但是定义方法五花八门,这样就导致使用统一的方式保存可调用对象或者传递可调用对象时,会十分繁琐。C++11中提供了std::function和std::bind统一了可调用对象的各种操作。

std::function

std::function是C++标准库中的一个函数对象封装器,是一个类模板;它可以用来存储、复制和调用任何可调用对象(函数、函数指针、成员函数指针、lambda表达式等)。它提供了一种通用的方式来处理不同类型的可调用对象,并允许保存和延迟它们的执行,使得代码更加灵活和可扩展。

std::function的官方定义:
template<class R, class... Args>
 function<R(Args...)>;

std::function的作用:

  1. 函数对象存储和调用:std::function可以用来存储不同类型的可调用对象,并且可以通过调用operator()来执行些对象。例如:
    #include <iostream>
    #include <functional>
    int add(int a, int b) {
      return a + b;
    }
    int main() {
      std::function<int(int, int)> func = add;
      std::cout << func(1, 2) << std::endl;  // 输出3
      return 0;
    }
    
  2. 函数回调:std::function可以作为回调函数的类型,用于在特定事件发生时执行相应的操作。例如:
    // 示例 1 
    #include <iostream>
    #include <functional>
    void foo() {
      std::cout << "Hello, world!" << std::endl;
    }
    void callFunc(std::function<void()> func) {
      func();
    }
    int main() {
      std::function<void()> func = foo;
      callFunc(func);  // 输出:Hello, world!
      return 0;
    }
    // 示例 2
    #include <iostream>
    #include <functional>
    // 回调函数类型定义
    typedef std::function<void(int)> CallbackFunc;
    // 回调函数
    void callback(int value) {
      std::cout << "Callback function called with value: " << value << std::endl;
    }
    // 带参回调函数
    void performCallback(int value, CallbackFunc callbackFunc) {
      std::cout << "Performing callback with value: " << value << std::endl;
      callbackFunc(value);
    }
    int main() {
      CallbackFunc func = callback;  // 创建std::function对象,并绑定回调函数
      performCallback(42, func);  // 调用带参回调函数,传入回调函数对象
      return 0;
    }
    
  3. 函数的延迟调用:std::function可以用于延迟调用函数,即在某个特定的时机才执行函数。例如:
    #include <iostream>
    #include <functional>
    void delayedCall(const std::function<void()>& func) {
      // 延迟一段时间后执行函数
      std::this_thread::sleep_for(std::chrono::seconds(1));
      func();
    }
    int main() {
      std::function<void()> func = []() {
        std::cout << "Delayed call" << std::endl;
      };
      delayedCall(func);  // 延迟1秒后输出:Delayed call
      return 0;
    }
    

std::bind

std::bind是C++标准库中的一个通用的函数适配器,是一个函数模板;创建一个可调用对象(函数对象或者函数指针)的绑定副本。它可以将函数的参数和调用方式进行绑定,生成一个新的可调用对象。并且可以延迟调用原始可调用对象,以及在需要时提供参数。

std::bind的官方定义:
template< class F, class... Args >
constexpr /*unspecified*/ bind( F&& f, Args&&... args );

std::bind的作用:

  1. 绑定函数的参数:可以将函数的部分参数绑定到指定的值,从而创建一个新的可调用对象。示例代码如下:
    #include <iostream>
    #include <functional>
    void printSum(int a, int b) {
      std::cout << "Sum: " << a + b << std::endl;
    }
    int main() {
      auto printSumBind = std::bind(printSum, 10, std::placeholders::_1);
      printSumBind(20);  // 输出:Sum: 30
        return 0;
    }
    
  2. 绑定成员函数:可以将成员函数绑定到对象上,从而创建一个新的可调用对象。示例代码如下:
    #include <iostream>
    #include <functional>
    class MyClass {
    public:
      void printMessage(const std::string& message) {
        std::cout << "Message: " << message << std::endl;
      }
    };
    int main() {
      MyClass obj;
      auto printMessageBind = std::bind(&MyClass::printMessage, &obj, std::placeholders::_1);
      printMessageBind("Hello");  // 输出:Message: Hello
      return 0;
    }
    
  3. 函数指针的绑定:
    #include <iostream>
    #include <functional>
    void printMessage(const std::string& message) {
        std::cout << "Message: " << message << std::endl;
    }
    int main() {
        auto printFunc = std::bind(printMessage, std::placeholders::_1);
        printFunc("Hello"); // 输出:Message: Hello
        return 0;
    }
    
  4. 函数对象的延迟调用:
    #include <iostream>
    #include <functional>
    void printMessage(const std::string& message) {
        std::cout << "Message: " << message << std::endl;
    }
    int main() {
        auto printFunc = std::bind(printMessage, "Hello");
        printFunc(); // 输出:Message: Hello
        return 0;
    }