C++11 std::function、std::bind

来源:互联网 发布:白光触摸屏 编程软件 编辑:程序博客网 时间:2024/05/21 11:01

1. function

std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(像函数指针这类可调用实体,是类型不安全的)。

关于function的例子:

#include < functional>std::function< size_t (const char*) > print_func;// normal function -> std::function objectsize_t CPrint(const char*) { ... }print_func = CPrint;print_func("hello world"):// functor -> std::function objectclass CxxPrint{public:    size_t operator()(const char*) { ... }};CxxPrint p;print_func = p;print_func("hello world");

通过std::function的包裹,我们可以像传递普通的对象一样来传递可调用实体,很好地解决了类型安全的问题。

可调用实体转换为std::function对象需要遵守以下两条原则:
a. std::function对象的参数能转换为可调用实体的参数
b. 可调用实体的返回值能转换为std::function对象的返回值(注意,所有的可调用实体的返回值都与返回void的std::function对象的返回值兼容)。

2. bind

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

std::bind可以说是一个可调用实体的adapter。它可以预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调用实体,这种机制在回调函数的使用过程中颇为有用。

bind的语法格式:

auto newCallable = bind(callable, arg_list); 

一个简单的例子:

#include <iostream>#include <functional>using namespace std;int Func(int x, int y){    cout << x << " " << y << endl;}class A{public:    int Func(int x, int y)    {        cout << x << " " << y << endl;    }};int main(){    auto bf1 = std::bind(&Func, 10, std::placeholders::_1);    bf1(20); // same as Func(10, 20)    A a;    auto bf2 = std::bind(&A::Func, a, std::placeholders::_1, std::placeholders::_2);    bf2(10, 20); // same as a.Func(10, 20)    std::function< int(int)> bf3 = std::bind(&A::Func, a, std::placeholders::_1, 100);    bf3(10); // same as a.Func(10, 100) }// 注意,对于普通函数Func,前面的&可加可不加;// 对于成员函数A::Func,前面的&必须加,同时需要传入this参数(上例中是&a),写a或者&a都是可以的。

bf1把一个两个参数的普通函数的第一个参数绑定为10,生成了一个新的一个参数的可调用实体体;
bf2把一个类成员函数绑定了类对象,生成了一个像普通函数一样的新的可调用实体;
bf3把类成员函数绑定了类对象和第二个参数,生成了一个新的std::function对象。

bind的参数里带下划线的数字称为placeholder,表示新函数的第几个参数。std::placeholders是一个占位符。

比如:

auto g = bind(f, a, b, _2, c, _1);g(X, Y); //same as f(a, b, Y, c, X);

bind默认是传值的,如果想要用引用,需要ref或cref函数,后者是常引用,也都位于functional头文件。

如:

void f(int &a, const int &b, ...);auto g = bind(f, ref(a), cref(b).....)

题外话:

有&引用为什么还要有ref?

一个只接收值类型的模板,但是想传递一个引用参数给它,这时候就要用std::ref了。

在模板自动推导类型时,ref能用包装类型reference_wrapper来代替原本会被识别的值类型,而reference_wrapper能隐式转换为被引用的值的引用类型。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 注册支付宝的手机号成空号了怎么办 银行保本理财回执单丢了怎么办 电脑连不上网ip地址错误怎么办 邮箱填错了没收到面试通知怎么办 电信烽火网络机顶盒零配置中怎么办 专技天下学错科目了怎么办 注册公司行业大类选错了怎么办 私营企业开的车比领导好怎么办 有公司有商标无生产资质怎么办 天猫店铺使用商标被注销怎么办 入仓件快递员搞错入仓号怎么办 商标注册证盖了自己公司的章怎么办 普通机打发票作废票丢了怎么办 淘宝店铺被买家投诉工商介入怎么办 淘宝退货运单号填错了怎么办 微信没有绑手机号密码忘了怎么办 淘宝联盟账号和密码忘记了怎么办 社保用户名和密码都忘记了怎么办 江西银行网银用户名忘了怎么办 邮政银行网银登录密码忘了怎么办 建行网银支付密码忘了怎么办 建行手机网银登录密码忘了怎么办 特岗教师忘记用户名和密码怎么办 特岗教师用户名和密码忘了怎么办 电信登录用户名和密码忘记了怎么办 电脑登录用户名和密码忘了怎么办 电脑网络用户名忘了连不上网怎么办 微博忘记登录名怎么办只记得昵称 买房子付了首付现在要退房怎么办 玩lol延迟高怎么办但网速没问题 中维世纪监控密码忘记了怎么办 原店主营业执照不注销怎么办新的 苹果手机铃声调到最大还小怎么办 投标时措施费忘记套价了怎么办 美团商家更改手机号和银行卡怎么办 淘宝买的衣服颜色发错了怎么办 在淘宝买的衣服颜色不一样怎么办 新买的木柜气味好重怎么办 淘宝店铺动态评分一直很低怎么办? 刚生下来的宝宝睡觉不吃奶怎么办 宝宝吐奶咳嗽了可能被呛到怎么办