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. codeblock设置快捷键

    第一步: 第二步: 第三步:  格式化代码设置: 在代码框里点右键,按Format use Astyle就会自动代码格式化了 但是它默认的风格是大括号另起一行,很不习惯,实际上是可以改的 1.Sett ...

  2. 移除元素(remove,remove_if...unique...)

    remove 因为本算法作用的是iterator,所以并不会改变Container大小,会返回一个新的iterator new_last,是的first到new_last中的元素都不等于value,左 ...

  3. JavaScript编码风格

    最近在看前端大牛Nicbolas C.Zakas的<编写可维护的JavaScript代码>一书.觉得里面的很多知识点都写的很好,所以,就写篇博文,总结一下吧!编码规范对于程序设计来说是很重 ...

  4. 混合pyqt和qtcreator (2): Impl a image viewer (can show FIji ROI manager data)

    # -*- coding: utf-8 -*- """ Simple demonstration of TreeWidget, which is an extension ...

  5. mydumper安装、原理介绍

    一.安装   安装依赖包: yum install glib2-devel mysql-devel zlib-devel pcre-devel openssl-devel cmake 下载二进制包: ...

  6. kafka 中的术语

    出处:https://tech.meituan.com/2015/01/13/kafka-fs-design-theory.html table th:first-of-type { width: 7 ...

  7. vue-cli 2.x 项目优化之:引入本地静态库文件

    demo地址:https://github.com/cag2050/vue_cli_optimize_static_resource vue-cli 将静态资源文件放到 static 文件夹下并引用: ...

  8. python之numpy.power()数组元素求n次方

    numpy.power(x1, x2) 数组的元素分别求n次方.x2可以是数字,也可以是数组,但是x1和x2的列数要相同. >>> x1 = range(6) >>> ...

  9. cvsnt报错:Administrator: Switch to user failed due to configuration error. Contact your System Administrator

    在安装CVSNT一开始用Administrator登录时总是报[login aborted]Switch to user failed due to configuration error. Cont ...

  10. Jmeter使用自定义编写代码

    原文地址:http://blog.csdn.net/li_ok/article/details/1487685 我们在做性能测试时,有时需要自己编写测试脚本,很多测试工具都支持自定义编写测试脚本,比如 ...