C++之STL std::function及std::bind总结

std::function

        std::function是一种通用、多态的函数封装的类模板。本文将深入介绍它的功能和用法,并演示如何利用  std::function对C++中各种可调用实体(普通函数、函数指针、lambda表达式及其他函数对象等)进行封装,从而实现函数回调、实现策略模式以及解耦代码等常见应用场景。

std::function原型

template<class R,class... Args>
class function<R(Args...)>

    R是返回值类型,Args是函数的参数类型,实例一个std::function对象很简单,就是将可调用对象的返回值类型和参数类型作为模板参数传递给std::function模板类。比如:

std::function<void()> func1;
std::function<int(int,int)> func2;

std::function用法

    std::function包含于头文件 #include<functional>中,可将各种可调用实体进行封装统一,包括

  • 普通函数
  • lambda表达式
  • 函数指针
  • 仿函数(functor 重载括号运算符实现)
  • 类成员函数
  • 静态成员函数

下面通过几个例子说明其用法;

注:调用类成员函数时,需要和std::bind一起使用;

#include<iostream>
#include<functional>

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

//2.lamda表达式
auto plus_lamda = [](int a,int b)->int{
    return a + b;
};

//3.仿函数
class plus_func{
    public:
    int operator()(int a,int b){
        return a + b;
    }
};

//4.类成员函数 && 类静态函数
class plus_class{
    public:
        inline int plus(int a,int b)
        {
            return a + b;
        }

        static int plus_static(int a,int b)
        {
            return a + b;
        }
};
int main()
{
    std::function<int(int,int)> f1 = plus;
    std::cout<< "function:" << f1(1,2) << std::endl;
    std::function<int(int,int)> f2 = plus_lamda;
    std::cout<< "function lamda:" << f2(1,2) << std::endl;
    std::function<int(int,int)> f3 = plus_func();
    std::cout<< "function 3:" << f3(1,2) << std::endl;
    plus_class pc;
    std::function<int(int,int)> f4 = std::bind(&plus_class::plus,pc,std::placeholders::_1,std::placeholders::_2);
    std::cout<< "function class func:" << f4(1,2) << std::endl;
    std::function<int(int,int)> f5 = plus_class::plus_static;
    std::cout<< "function class static func:" << f5(1,2) << std::endl;
    return 0;
}

std::function缺点

        std::function填补了函数指针的灵活性,但会对调用性能有一定损耗,经测试发现,在调用次数达10亿次时,函数指针比直接调用要慢2秒左右,而std::function要比函数指针慢2秒左右,这么少的损耗如果是对于调用次数并不高的函数,替换成std::function绝对是划得来的。

std::bind

        std::bind是一个函数模板,将可调用对象和可调用对象的参数进行绑定,返回新的可调用对象(std::function类型,参数列表可能改变),返回的新的std::function可调用对象的参数列表根据bind函数实参中std::placeholders::_x从小到大对应的参数确定。

std::bind原型

template<typename _Func, typename... _BoundArgs>
typename
_Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type
bind(_Func&& __f, _BoundArgs&&... __args)

std::bind用法        

示例:

#include <iostream>
#include <functional>

int plus(int a, int b) {
    return a + b;
}

class plus_class{
    public:
        int plus(int a,int b){
            return a + b;
        }
};

int main() {
    std::function<int(int)> plus_ten = std::bind(plus, 10, std::placeholders::_1);
    std::cout << plus_ten(10) << std::endl; // 输出 20
    plus_class pc;
    std::function<int(int,int)> plus_two_num = std::bind(&plus_class::plus,&pc, std::placeholders::_1,std::placeholders::_2);
    std::cout << plus_two_num(10,20) << std::endl; // 输出 30
    return 0;
}

        bind第一个参数传入一个函数、函数指针、lamda表达式、类的成员函数都是可以的,这里注意,如果是类的成员函数,则需要再类的作用域前加上&,第二个占位符需要注意,如果不是类的成员函数,那么直接要么是一个参数,例如10,或者std::placeholders::_1(由调用bind返回值时传入),如果是类的成员函数,第二个参数是实例化的类对象,第三个参数开始才是函数的输入参数。也可参考std::function对于类的成员函数的调用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值