【现代C++特性】函数对象包装器std::function与函数参数绑定器std::bind

132 阅读2分钟

一、函数对象包装器std::function

在C++11中,将可被调用的对象类型,统称为可调用类型。

std::function是一个类模板,是一种通用、多态的函数封装,其实例可对任意可调用的目标实体进行存储、复制和调用操作,即对C++代码中现有的可调用实体的一种类型安全的封装(相对于函数指针来说)。通过指定它的模板参数,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟执行它们。

所以std::function就是函数的容器,方便函数、函数指针作为对象处理。 通过函数指针的传递,在其他函数合适的位置调用这个包装好的仿函数。

对于模板函数,使用std::function将模板参数进行封装,以减少模板的实例化次数。

二、函数参数绑定器std::bind

  1. std::bind 可用来绑定函数调用的参数,当无法一次性获得调用某个函数的全部参数时,通过std::bind与std::placeholder组合使用,将部分调用参数提前绑定到函数身上成为一个新的对象,即将多元(参数个数为n,n>1)可调用对象转换为一元或者(n-1)元可调用对象,只绑定部分参数。参数的位置与传入的位置相关,调用时参数必须齐全。 std::placeholders::_1是一个占位符,当函数传入第一个参数的时候,就会把其进行替换,同理std::palceholders::_2是第二个占位符。

  2. std::bind 也可用来将可调用对象与其参数绑定成一个仿函数,绑定后的结果使用std::function进行保存,并延迟调用。std::bind绑定器返回的是一个仿函数类型,得到的返回值可以直接赋值给一个std::function,在使用的时候我们并不需要关心绑定器的返回值类型,或者不确定一个函数的返回值类型时,使用auto进行自动类型推导就可以了。

#include <functional>
#include <iostream>void test_Func(int a, int b, int c)
{
    std::cout << a << std::endl;
    std::cout << b << std::endl;
    std::cout << c << std::endl;
}

int main()
{
    // 1. std::function
    // 包装test_Func为func_1函数对象
    std::function<void(int)> func_1 = test_Func;
    func_1(1, 2, 3);
    
    // 2. std::bind
    // 将参数1,2绑定到函数test_Func上,使用std::placeholders::_1对第一个参数占位
    auto func_2 = std::bind(test_Func, std::placeholders::_1, 2, 3);
    func_2(100); // 调用时再传入第一个参数
 }