C++11中的std::bind
C++11中的std::bind
最近在看看cocos2dx的源代码,发现了cocos2dx 3.0相对于2.0改动了很多,最大的改变就是大量的使用了C++11的特性,比如auto等。其中有一个关于回调函数绑定的宏定义就使用了std::bind特性
// new callbacks based on C++11
#define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
#define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
#define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__)
非常简练的宏定义,对于没有接触过C++11的朋友来说,真的是一头雾水,这货是什么,真的是C++吗?所以笔者就写了这篇文章来讲解。
C++发展的历史
C++经过多年发展,真正正式公布出的标准只有三个C++98,C++03,C++11。其中C++03只是C++98的小幅度修订,在笔者看来,C++发展的历史,就是一个不断吸收新特性的历史。从最早的面向过程,面向对象,模板编程,到现在的函数式编程,C++一直都是在吸收新特性。lambda就是函数式编程闭包的特性。
何为bind
bind是这样一种机制,它可以预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调 用实体,这种机制在回调函数的使用过程中也颇为有用。其实最早在C++98的时候,就已经有了std::bind1st和std::bind2nd分别用来绑定functor的两个参数,具体代码就不演示了,查查资料就知道了。这个特性在当时并没有引起太多的重视,可以说是食之无味。
C++11中提供了std::bind,可以说是一种飞跃的提升,bind本身是一种延迟计算的思想,它本身可以绑定普通函数、全局函数、静态函数、类静态函数甚至是类成员函数。
#include <iostream>
#include <functional>
using namespace std;
int TestFunc(int a, char c, float f)
{
cout << a << endl;
cout << c << endl;
cout << f << endl;
return a;
}
int main()
{
auto bindFunc1 = bind(TestFunc, std::placeholders::_1, 'A', 100.1);
bindFunc1(10);
cout << "=================================\n";
auto bindFunc2 = bind(TestFunc, std::placeholders::_2, std::placeholders::_1, 100.1);
bindFunc2('B', 10);
cout << "=================================\n";
auto bindFunc3 = bind(TestFunc, std::placeholders::_2, std::placeholders::_3, std::placeholders::_1);
bindFunc3(100.1, 30, 'C');
return 0;
}
从上面的代码可以看到,bind能够在绑定时候就同时绑定一部分参数,未提供的参数则使用占位符表示,然后在运行时传入实际的参数值。
PS:绑定的参数将会以值传递的方式传递给具体函数,占位符将会以引用传递。
众所周知,静态成员函数其实可以看做是全局函数,而非静态成员函数则需要传递this指针作为第一个参数,所以std::bind能很容易地绑定成员函数。
cocos2dx中的CC_CALLBACK系列的宏其实就是一种封装好的std::bind,它默认认为绑定的就是成员函数,帮助开发者简化了代码。
总结
bind最终将会生成一个可调用对象,这个对象可以直接赋值给std::function对象,而std::bind绑定的可调用对象可以是Lambda表达式或者类成员函数等可调用对象,这个是cocos2dx中的一般用法。它能随意绑定任何函数,将所有的函数都能统一到std::function
example:
#include <iostream>
#include <typeinfo>
#include <functional>
#include <string.h>
#include <iostream>
#include <typeinfo>
#include <functional>
#include <string.h>
using namespace std; int add(int a, int b, int c)
{
return a+b+c;
} class Utils{
public:
Utils(const char* name){
strcpy(_name, name);
} void SayHello(const char* name) const{
std::cout<<_name<<" say : hello "<<name<<endl;
} static int getId(){
return ;
} private:
char _name[];
}; int main()
{
auto add2 = std::bind(add, std::placeholders::_1, , );
int i=add2();
std::cout<<i<<std::endl;
std::cout<<typeid(add2).name()<<endl; cout<<"------------------------------------"<<endl; Utils util("xiaoming");
//绑定类成员
auto sayHello = std::bind(&Utils::SayHello, util, std::placeholders::_1);
sayHello("xiaodonmg"); auto SayHelloKit = std::bind(&Utils::SayHello, util, "kit");
SayHelloKit(); //绑定静态成员
auto getId = std::bind(&Utils::getId);
cout<<getId()<<endl; return ;
}
C++11中的std::bind的更多相关文章
- C++11中的std::function
看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed; std::fun ...
- 【转】C++11中的std::function
原文地址:http://www.jellythink.com/archives/771 看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard: ...
- C++11 中function和bind以及lambda 表达式的用法
关于std::function 的用法: 其实就可以理解成函数指针 1. 保存自由函数 void printA(int a) { cout<<a<<endl; } std:: ...
- c++11中关于std::thread的join的思考
c++中关于std::thread的join的思考 std::thread是c++11新引入的线程标准库,通过其可以方便的编写与平台无关的多线程程序,虽然对比针对平台来定制化多线程库会使性能达到最大, ...
- 关于C++11中的std::move和std::forward
std::move是一个用于提示优化的函数,过去的c++98中,由于无法将作为右值的临时变量从左值当中区别出来,所以程序运行时有大量临时变量白白的创建后又立刻销毁,其中又尤其是返回字符串std::st ...
- [C/C++]关于C++11中的std::move和std::forward
http://www.cnblogs.com/cbscan/archive/2012/01/10/2318482.html http://blog.csdn.net/fcryuuhou/article ...
- c++11中关于`std::thread`线程传参的思考
关于std::thread线程传参的思考 最重要要记住的一点是:参数要拷贝到线程独立内存中,不管是普通类型.还是引用类型. 对于传递参数是引用类型,需要注意: 1.当指向动态变量的指针(char *) ...
- C++11中提供了std::bind
再来看看std::bind C++11中提供了std::bind.bind()函数的意义就像它的函数名一样,是用来绑定函数调用的某些参数的. bind的思想实际上是一种延迟计算的思想,将可调用对象保存 ...
- C++11 中的function和bind、lambda用法
std::function 1. std::bind绑定一个成员函数 #include <iostream> #include <functional> struct Foo ...
随机推荐
- cobbler相关
Cobbler通过将设置和管理一个安装服务器所涉及的任务集中在一起,从而简化了系统配置.相当于Cobbler封装了DHCP.TFTP.XINTED等服务,结合了PXE.kickstart等安装方法,可 ...
- [2019/05/17]解决springboot测试List接口时JSON传参异常
报错信息,大致如下 c.c.c.c.a.BaseControllerExceptionHandler : 运行时异常: java.lang.IllegalStateException: No prim ...
- test20190829 神大校赛模拟
100+100+0=200,聪明搬题人题面又出锅了. 最短路径(path) 给定有向图,包含 n 个节点和 m 条有向边. 一条A 到 B 的路径是最短路径当且仅当不存在另一条从A 到 B 的路径比它 ...
- test20190814 NOIP2019 模拟题
二叉树 [问题描述] 从前有一棵二叉树,我们用如下方式来表示这棵二叉树. 如果一个节点没有儿子,我们用"0"来表示他. 如果一个节点有一个儿子,我们对它的表示以"1&qu ...
- wamp——添加多版本PHP
前言 从下载到部署,手把手教学~ wamp 版本 | 3.0.4 32位 步骤 下载PHP 进入网站https://windows.php.net/download然后选择想要的版本下载 注意点: . ...
- 3. 控制反转(IoC)和依赖注入(DI)
1).控制反转是应用于软件工程领域中的,在运行时被装配器对象来绑定耦合对象的一种编程技巧,对象之间耦合关系在编译时通常是未知的.在传统的编程方式中,业务逻辑的流程是由应用程序中的早已被设定好关联关系的 ...
- LightOJ - 1226 - One Unit Machine(排列组合)
链接: https://vjudge.net/problem/LightOJ-1226 题意: OUM is a one unit machine which processes jobs. Sinc ...
- P4462 [CQOI2018]异或序列 莫队
题意:给定数列 \(a\) 和 \(k\) ,询问区间 \([l,r]\) 中有多少子区间满足异或和为 \(k\). 莫队.我们可以记录前缀异或值 \(a_i\),修改时,贡献为 \(c[a_i\bi ...
- learning java Runtime类中的exec
var rt = Runtime.getRuntime(); // 类c语言当中的system()函数. rt.exec("notepad.exe");
- 计数 luogu 4223 期望逆序对
https://www.luogu.org/problemnew/show/P4223 期望乘以\(\binom {n}{2}^k\)变成了计数问题 我们考虑每一组数\((A, B)\)产生的贡献CC ...