1. 温故知新:std::bind1st和std::bind2nd

(1)bind1st、bind2nd首先它们都是函数模板,用于将参数绑定到可调用对象(如函数、仿函数等)的第1个或第2个参数上

(2)函数的返回值是一个函数对象。它用于包装和改造传入的函数(或仿函数),并形成一个新的仿函数对象(是一个可调用对象)

(3)与旧的可调用对象相比,新的仿函数对象参数个数少了1个。(相当于给少掉的那个参数一个默认的值

2. std::bind绑定器

(1)首先,std::bind也是一个函数模板,返回值是一个仿函数,也是可调用对象。它的作用与bind1st和bind2st类似,是这两个函数的加强版。但极大地提高了灵活性,可以完全替代bind1st和bind2nd。

(2)bind的作用主要就是将可调用对象变成std::function对象(即仿函数对象),主要体现在两个方面。

  ①将多元的可调用对象与其参数一起绑定成一个仿函数对象。

  ②将多元(设参数个数为n)的可调用对象转成一元或(n-1)元的可调用对象,即只绑定部分参数

(3)std::bind可以绑定的对象(注意bind的返回值是仿函数)

  ①普通函数(functions);

  ②函数对象(仿函数,function objects);

  ③类的成员函数(member functions。注意:_1必须是某个对象的地址

  ④类的数据成员(data members注意:_1必须是某个对象的地址

【编程实验】std::bind初探

#include <iostream>
#include <vector>
#include <functional> // for std::bind
#include <typeinfo> using namespace std::placeholders; //让_1, _2, _3,...可见!
using namespace std; //除法函数:x/y
double my_divide(double x, double y)
{
return x / y;
} struct MyPair
{
double a, b;
MyPair(int a, int b):a(a), b(b)
{ cout << "MyPair(int a, int b)" << endl;
}
//注意成员函数的第1个参数是this!!!
double mutiply(){return a * b;}
}; int main()
{
//1、绑定函数
auto fn1 = bind(my_divide, , ); //返回一个std::function类型的仿函数
//function<double(void)> fn1 = bind(my_divide, 10, 2); //绑定完,fn1是无参,所以为void
//cout << typeid(fn1).name() << endl;
cout << fn1() << endl; auto fn2 = bind(my_divide, _1, ); //my_divide的第2个参数绑定为2
cout << fn2() << endl; // 输出5
//cout << fn2(10, 3) << endl; // 输出仍然为5! auto fn3 = bind(my_divide, _2, _1);
cout << fn3(, ) << endl; //输出:0.2。注意10为第1个参数,被绑到_1的位置,2绑到_2的位置 auto fn4 = bind<int>(my_divide, _1, _2); //指定返回值为int型
cout << fn4(, ) << endl; //2、绑定类的成员
MyPair mp{, }; //注意,mp是个聚合对象,可用{}直接初始化(虽无2个参数的构造函数)。 auto ftor_memfn = bind(&MyPair::mutiply, _1); //成员函数,其实有个this指针,须放入_1
cout << ftor_memfn(mp) << endl; //20,传入mp对象的地址(这里传的是引用) auto ftor_memdata = bind(&MyPair::a, mp); //传mp对象的副本,
//auto ftor_memdata = bind(&MyPair::a, &mp); //传mp的地址
cout << ftor_memdata() << endl; //
ftor_memdata() = ; //mp副本的a值被改为100
cout << mp.a << endl; //10,mp本身的a值未被改变,仍为10
cout << ftor_memdata() << endl; auto ftor_memdata2 = bind(&MyPair::b, _1);
cout << ftor_memdata2(mp) << endl; //
ftor_memdata2(mp) = ; //传mp的引用
cout << mp.b << endl; //由于按引用传递,b的值被改!
cout << ftor_memdata2(mp) << endl; return ;
}

3. 使用std::bind的注意事项

(1)bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数是按值传递的

(2)对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。注意,对于placeholder是按引用传递的。

(3)通过placeholder可以改变传参的顺序。同时如果放置了placeholder_x的占位符,当调用时就必须给足至少x个实参

(4)bind的返回值是可调用实体,可以直接赋值给std::function对象

(5)对于绑定的指针、引用类型的参数,使用者需要保证在可调用对象调用之前,这些参数是可用的。

【编程实验】placeholder、组合使用bind函数

#include <iostream>
#include <vector>
#include <algorithm> //for count_if
#include <functional> // for std::bind using namespace std;
using namespace std::placeholders; void output(int x, int y)
{
cout << x << ", " << y << endl;
} int main()
{
auto out1 = bind(output, _1, );
out1(); //输出:1, 2 auto out2 = bind(output, , _1);
out2(); //输出:2, 1 auto out3 = bind(output, , _2);
out3(, ); //输出2, 3(注意,第1个参数被默认的2取代了)
//out3(1); //error, 调用时需给出第2个参数 auto out4 = bind(output, , _2);
out4(, ); //输出2, 3
//out4(1); //error, 调用时需给出第2个参数 auto out5 = bind(output, _2, _1);
out5(, ); //输出3, 1(第1个实参对应_1,第2个实参对应_2) vector<int> v{, , , , , , , }; //通过bind2nd绑定
int n = count_if(v.begin(), v.end(), not1(bind2nd(less<int>(), )));
cout <<"n = " << n << endl; //5(大于等于50的元素个数) //通过bind绑定
auto fn = bind(less<int>(), _1, );
cout << count_if(v.begin(), v.end(), fn) << endl; //3,小于50的元素个数
cout << count_if(v.begin(), v.end(), bind(less<int>(), _1, )) << endl; //3 //组合使用bind
//查找(50,73]之间的元素个数
auto f = bind(logical_and<bool>(), bind(greater<int>(), _1, ), bind(less_equal<int>(), _1, ));
cout << count_if(v.begin(), v.end(), f) << endl; // return ;
}

第11课 std::bind和std::function(2)_std::bind绑定器的更多相关文章

  1. C++11绑定器bind及function机制

    前言 之前在学muduo网络库时,看到陈硕以基于对象编程的方式,大量使用boost库中的bind和function机制,如今,这些概念都已引入至C++11,包含在头文件<functional&g ...

  2. 箭头函数表达式和声名式函数表达式的区别以及 Function.prototype的bind, apply,call方法

    箭头函数不能用做构造函数 箭头函数没有arguments参数 箭头函数没有自己的this,是从作用域链上取this,是与箭头函数定义的位置有关的,与执行时谁调用无关,所以用call,apply,bin ...

  3. 第12课 std::bind和std::function(3)_std::function可调用对象包装器

    1. std::function (1)首先是一个类模板,用于包装可调用对象.可以容纳除了类成员(函数)指针之外的所有可调用对象. (2)可以将普通函数,lambda表达式和函数对象类统一起来.尽管它 ...

  4. c++11特性与cocos2d-x 3.0之std::bind与std::function

    昨天同事让帮忙写一小功能,才发现cocos2d-x 3.0 和 cocos2d-x 3.0rc0 差别还是相当大的. 发现Label这一个控件,3.0就比rc0版本多了一个创建函数,更为关键的是3.0 ...

  5. c++11——std::function和bind绑定器

    c++11中增加了std::function和std::bind,可更加方便的使用标准库,同时也可方便的进行延时求值. 可调用对象 c++中的可调用对象存在以下几类: (1)函数指针 (2)具有ope ...

  6. C++11 学习笔记 std::function和bind绑定器

    C++11 学习笔记 std::function和bind绑定器 一.std::function C++中的可调用对象虽然具有比较统一操作形式(除了类成员指针之外,都是后面加括号进行调用),但定义方法 ...

  7. C++11新特性之二——std::bind std::function 高级用法

    /* * File: main.cpp * Author: Vicky.H * Email: eclipser@163.com */ #include <iostream> #includ ...

  8. std::bind和std::function

    std::bind 用于绑定一个函数,返回另外一种调用方式的函数对象 ,可以改变参数顺序 和个数,特别是在多线程的程序中,经常用它将函数进行包装,然后打包发送给工作线程,让工作线程去执行我们的任务. ...

  9. C++ 11 Lambda表达式、auto、function、bind、final、override

    接触了cocos2dx 3.0,就必须得看C++ 11了.有分享过帖子:[转帖]漫话C++0x(四) —- function, bind和lambda.其实最后的Lambda没太怎么看懂. 看不懂没关 ...

随机推荐

  1. timescaledb 集成 madlib

    github 上有人提出了一个问题(2017 很早了),然后搜索timescaledb 的docs 文档,发现有 一片介绍的文章,所以尝试运行下 备注: 环境使用虚拟机安装(没有使用docker ma ...

  2. 人教版高中数学(A版)

    必修1 (已看) 第一章 集合与函数概念 1.1 集合 1.2 函数及其表示 1.3 函数的基本性质 第二章 基本初等函数(1) 2.1 指数函数 2.2 对数函数 2.3 幂函数 第三章 函数的应用 ...

  3. COM,SOM, QT, GObject, ObjectiveC

    COM,SOM, QT, GObject, ObjectiveC https://en.wikipedia.org/wiki/IBM_System_Object_Model#Comparison_of ...

  4. zookeeper 学习资料

    zookeeper 学习资料 学习资料 网址 Zookeeper 教程(菜鸟教程) https://www.w3cschool.cn/zookeeper/

  5. 代理模式proxy

    代理模式的共同优点如下: (1) 能够协调调用者和被调用者,在一定程度上降低了系统的耦合度. (2) 客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原则,系统具有较好的灵 ...

  6. xcrun: error: invalid active developer path

    问题 mac升级到10.12(macOS Sierra),执行命令,出现如下错误: xcrun: error: invalid active developer path (/Library/Deve ...

  7. 自然语言处理工具python调用hanlp中文实体识别

    Hanlp作为一款重要的中文分词工具,在GitHub的用户量已经非常之高,应该可以看得出来大家对于hanlp这款分词工具还是很认可的.本篇继续分享一篇关于hanlp的使用实例即Python调用hanl ...

  8. 多线程中的Lock小结

    出处:http://www.cnblogs.com/DarrenChan/p/6528578.html#undefined 1.lock和synchronized的区别 1)Lock不是Java语言内 ...

  9. 阿里巴巴Java编码规范,来测测你能得多少分

    今年年初,<阿里巴巴Java开发手册>正式发布,阿里官方Java代码规范标准首次对外公开.手册发布之后在业界.学术界都获得了广泛的关注,仅微博浏览量就突破千万,下载访问量超过40万,多家媒 ...

  10. Linux之chgrp

    命令功能: 在lunix系统里,文件或目录的权限的掌控以拥有者及所诉群组来管理.可以使用chgrp指令取变更文件与目录所属群组,这种方式采用群组名称或群组识别码都可以.Chgrp命令就是change  ...