1、可调用对象

可调用对象有一下几种定义:

  • 是一个函数指针,参考 C++ 函数指针和函数类型;
  • 是一个具有operator()成员函数的类的对象;
  • 可被转换成函数指针的类对象;
  • 一个类成员函数指针;

C++中可调用对象的虽然都有一个比较统一的操作形式,但是定义方法五花八门,这样就导致使用统一的方式保存可调用对象或者传递可调用对象时,会十分繁琐。C++11中提供了std::function和std::bind统一了可调用对象的各种操作。

不同类型可能具有相同的调用形式,如:

// 普通函数
int add(int a, int b){return a+b;} // lambda表达式
auto mod = [](int a, int b){ return a % b;}// 函数对象类
struct divide{int operator()(int denominator, int divisor){return denominator/divisor;}
};

上述三种可调用对象虽然类型不同,但是共享了一种调用形式:

int(int ,int)

std::function就可以将上述类型保存起来,如下:

std::function<int(int ,int)>  a = add;
std::function<int(int ,int)>  b = mod ;
std::function<int(int ,int)>  c = divide();

2、std::function

  • std::function是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。

  • 定义格式:std::function<函数类型>。

  • std::function可以取代函数指针的作用,因为它可以延迟函数的执行,特别适合作为回调函数使用。它比普通函数指针更加的灵活和便利。

3、std::bind

可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。

std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。std::bind主要有以下两个作用:

  • 将可调用对象和其参数绑定成一个防函数;
  • 只绑定部分参数,减少可调用对象传入的参数。

3.1 std::bind绑定普通函数

double my_divide (double x, double y) {return x/y;}
auto fn_half = std::bind (my_divide,_1,2);
std::cout << fn_half(10) << '\n';                        // 5
  • bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind (my_divide,_1,2)等价于std::bind (&my_divide,_1,2);
  • _1表示占位符,位于中,std::placeholders::_1;

3.2 std::bind绑定一个成员函数

struct Foo {void print_sum(int n1, int n2){std::cout << n1+n2 << '\n';}int data = 10;
};
int main()
{Foo foo;auto f = std::bind(&Foo::print_sum, &foo, 95, std::placeholders::_1);f(5); // 100
}
  • bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。
  • 必须显示的指定&Foo::print_sum,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在Foo::print_sum前添加&;
  • 使用对象成员函数的指针时,必须要知道该指针属于哪个对象,因此第二个参数为对象的地址 &foo;

3.3 绑定一个引用参数

默认情况下,bind的那些不是占位符的参数被拷贝到bind返回的可调用对象中。但是,与lambda类似,有时对有些绑定的参数希望以引用的方式传递,或是要绑定参数的类型无法拷贝。

#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <sstream>
using namespace std::placeholders;
using namespace std;ostream & print(ostream &os, const string& s, char c)
{os << s << c;return os;
}int main()
{vector<string> words{"helo", "world", "this", "is", "C++11"};ostringstream os;char c = ' ';for_each(words.begin(), words.end(), [&os, c](const string & s){os << s << c;} );cout << os.str() << endl;ostringstream os1;// ostream不能拷贝,若希望传递给bind一个对象,// 而不拷贝它,就必须使用标准库提供的ref函数for_each(words.begin(), words.end(),bind(print, ref(os1), _1, c));cout << os1.str() << endl;
}

4、指向成员函数的指针

通过下面的例子,熟悉一下指向成员函数的指针的定义方法。

#include <iostream>
struct Foo {int value;void f() { std::cout << "f(" << this->value << ")\n"; }void g() { std::cout << "g(" << this->value << ")\n"; }
};
void apply(Foo* foo1, Foo* foo2, void (Foo::*fun)()) {(foo1->*fun)();  // call fun on the object foo1(foo2->*fun)();  // call fun on the object foo2
}
int main() {Foo foo1{1};Foo foo2{2};apply(&foo1, &foo2, &Foo::f);apply(&foo1, &foo2, &Foo::g);
}
  • 成员函数指针的定义:void (Foo::*fun)(),调用是传递的实参: &Foo::f;
  • fun为类成员函数指针,所以调用是要通过解引用的方式获取成员函数*fun,即(foo1->*fun)();

原文链接:https://www.jianshu.com/p/f191e88dcc80

C++中std::function和std::bind相关推荐

  1. std::function和std::bind

    std::function和std::bind std::function 可调用对象 是一个函数指针 是一个具有operator()成员函数的类和对象 可被转换成函数指针的类对象: 一个类成员函数指 ...

  2. C++11 FAQ中文版:std::function 和 std::bind

    std::function 和 std::bind 标准库函数bind()和function()定义于头文件中(该头文件还包括许多其他函数对象),用于处理函数及函数参数.bind()接受一个函数(或者 ...

  3. 可调用对象、std::function、std::bind

    可调用对象.std::function.std::bind 仿函数functors function adapter bind(C++11) 函数适配器:bind2nd 仿函数适配器(mem_fun/ ...

  4. 【C++】C++11的std::function和std::bind用法详解

    在设计回调函数的时候,无可避免地会接触到可回调对象.在C++11中,提供了std::function和std::bind两个方法来对可回调对象进行统一和封装. 可调用对象 C++中有如下几种可调用对象 ...

  5. std::function和std::bind用法

    std::bind() std::bind 主要用于绑定生成目标函数,一般用于生成的回调函数,cocos的回退函数都是通过std::bind和std::function实现的.两个点要明白: 1.绑定 ...

  6. 【c++】24.std::function和std::bind详解

    1. 可调用对象 查看全文 http://www.taodudu.cc/news/show-494578.html 相关文章: [c++]26.浅谈"事件驱动".select.po ...

  7. C++11中的std::function

    文章转载自:http://www.jellythink.com/archives/771 看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard ...

  8. C++11 std::function, std::bind, std::ref, std::cref

    C++11 std::function, std::bind, std::ref, std::cref 转自:http://www.jellythink.com/ std::function 看看这段 ...

  9. 【C++】char uchar string stringstream queue array vector set map std::function std::bind

    文章目录 cout 防止使用科学计数法 一维数组的三种初始化方法 二维数组 vector作为参数的三种传参方式 vector 的 reserve resize set std::map std::pa ...

最新文章

  1. 博士申请 | 澳门大学汪澎洋助理教授招收机器学习方向全奖博士生
  2. angularjs http和ajax,AngularJS $ http和$ resource
  3. Hadoop机架感知
  4. 支付验证签名失败_验证码收不到,或许是验证码平台出了问题!
  5. 图片管理系统源码_「程序员分享」基于SpringBoot开发的天猫商城源码
  6. 编译在arm版本的Valgrind-转
  7. 规则引擎 drools_Drools的入门初探
  8. http抓包实践--(七)-fiddler弱网环境
  9. Retrofit完美封装
  10. 浏览器在线PDF预览取消下载按钮
  11. 计算机视觉硕士课程南京大学,南京大学计算机系研究生课程文库
  12. php开发h5游戏教程,HTML5游戏框架cnGameJS开发实录-实现动画原理
  13. 区块链、NFT与元宇宙中的稀缺性技术
  14. python人脸识别门禁_Python+Opencv+Tkinter指纹识别与人脸识别的门禁兼考勤(二)
  15. 32位机4G虚拟内存 64位机128G虚拟内存计算误区
  16. 文件上传漏洞初步解析(个人浅薄理解)
  17. 【C语言】数组的基本知识详细讲解(一维数组、二维数组、越界、存储.....
  18. 导出excel:下载模板时填充数据方法实现
  19. 手把手教您批量下载E宠商城多个商品图片并保存
  20. 【ijkplayer】介绍

热门文章

  1. python有哪些作用-python是什么 特点及功能
  2. python代码怎么运行-python代码如何运行
  3. 软件工程python就业方向-女生学习软件工程专业就业怎么样?
  4. python简单编程例子-python简单实例训练(21~30)
  5. linux查看python版本命令-linux 查看版本命令
  6. python对笔记本电脑的要求-学Python买什么笔记本电脑?
  7. python压缩包怎么安装-详解python解压压缩包的五种方法
  8. python语言自学-python语言学习笔记整理
  9. ROS调用本地摄像头数据并在rviz里显示
  10. 在导入graphsurgeon时报错:ImportError: cannot import name ‘NodeDef‘ from ‘tensorflow‘