std::bind 的使用说明
转自:
https://www.cnblogs.com/cmranger/p/4743926.html
/////////////////////
std::bind
bind是对C++98标准中函数适配器bind1st/bind2nd的泛化和增强,可以适配任意的可调用对象,包括函数指针、函数引用、成员函数指针和函数对象。bind
接受的第一个参数必须是一个可调用的对象f,可以是函数、函数指针、函数对象和成员函数指针,之后接受的参数的数量必须与f的参数数量相等,这些参数将被传递给f作为入参。
绑定完成后,bind会返回一个函数对象,它内部保存了f的拷贝,具有operator()
,返回值类型被自动
推导为f的返回值类型。反生调用时,这个函数对象将把之前存储的参数转发给f完成调用。
如:
int Add(int num1, int num2)
{
return (num1 + num2);
}
Add(1,2);
//等价于一个具有无参operator()的bind函数对象调用
std::bind(&Add,1,2)();
这是bind
最简单的形式。bind
表达式存储了Add和参数1,2的拷贝,产生了一个临时的函数对象。因为Add接受两个参数,而1,2都是实参,因此临时函数对象将具有一个无参的operator()
。当operator()
调用发生时函数对象把1、2的拷贝传递给Add,完成真正的调用。
bind
的真正威力在与占位符,_1 _2 _3 ...
,(为了避免与boost库的占位符冲突,标准占位符定义在std::placeholders
名字空间,使用时:std::placeholders::_1
),占位符可以取代bind中参数的位置,在发生函数调用时才接受真正的参数。
占位符的名字表示它在调用时中的顺序,而在绑定式中没有顺序要求。如下:
int Sub(int num1,int num2)
{
return (num1 - num2);
}
std::bind(&Sub,std::placeholders::_1,std::placeholders::_2)(2,1);
//等价于
Sub(2,1);
std::bind(&Sub,std::placeholders::_2,std::placeholders::_1)(2,1);
//等价于
Sub(1,2);
bind详细用法:
//普通全局函数
void Out( int & elem)
{
std::cout << elem << " ";
}
//类
template<typename T>
class Print
{
public:
Print(const char * prefix = "")
: _prefix(prefix)
, _printNum(0)
{
}
//非静态成员函数
void PrintElem(const T & elem)
{
_printNum++;
if (_printNum <= 1)
{
cout << "\n" << _prefix << ": ";
}
cout << elem << " ";
}
//静态成员函数
static void static_fun()
{
std::cout << "\nstatic func!";
}
private:
string _prefix;
size_t _printNum;
};
int arr[] = {1,2,1,3,4,8,9,8};
vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
//绑定普通函数
std::for_each(v.begin(),v.end(),std::bind(&Out,std::placeholders::_1));
//绑定类的非静态成员函数
//第一个占位符的位置必须是一个类的实例、引用或指针
Print<int> print("bind member function");
std::for_each(v.begin(),v.end(),
std::bind(&(Print<int>::PrintElem),&print,std::placeholders::_1));
//注:必须在成员函数前加上取地址操作符&,表明这是一个成员函数指针,否则会无法通过编译。
//绑定静态成员函数 与绑定全局函数没有区别
std::function<void(void)> ff = std::bind(&Print<int>::static_fun);
ff();
绑定函数对象:
bind可以绑定任意的函数对象,包括标准库中的所有预定义的函数对象。
如果函数对象有内部类型定义result_type
,那么bind可以自动推导出返回值类型,用法与绑定普通函数一样。否则,需要在绑定形式上做出变动,用模版参数指明返回类型。bind<result_type>(functiontor, ...)
标准库中大部分函数对象都有result_type
定义,因此不需要特别的形式。
//绑定预定义的函数对象
std::transform(v.begin(),v.end(),v.begin(),
std::bind(std::plus<int>(),std::placeholders::_1,10)); //绑定函数对象
//绑定自定义的函数对象
//要想bind 绑定自定义的函数对象,必须提供一些型别的成员来反映其参数和返回值的型别,
//为了方便,可以继承 binary_function等
template<typename T1, typename T2>
struct fopow : public std::binary_function<T1,T2,T1>
{
T1 operator() (T1 base, T2 exp) const
{
return std::pow(base,exp);
}
};
std::transform(v.begin(),v.end(),v.begin(),
std::bind(fopow<double,int>(),std::placeholders::_1,2));
//自己定义result_type
template<typename T>
struct MyPlus
{
typedef T argument_type;
typedef T result_type;
result_type operator() (const argument_type & arg1, const argument_type & arg2) const
{
return (arg1 - arg2);
}
};
std::function<int(int)> f = std::bind(MyPlus<int>(),std::placeholders::_1,10);
std::transform(v.begin(),v.end(),v.begin(),f);
补充:
//binary_function原型
template<class _Arg1,
class _Arg2,
class _Result>
struct binary_function
{ // base class for binary functions
typedef _Arg1 first_argument_type;
typedef _Arg2 second_argument_type;
typedef _Result result_type;
};
std::bind 的使用说明的更多相关文章
- C++11之std::function和std::bind
std::function是可调用对象的包装器,它最重要的功能是实现延时调用: #include "stdafx.h" #include<iostream>// std ...
- std::bind和std::function
std::bind 用于绑定一个函数,返回另外一种调用方式的函数对象 ,可以改变参数顺序 和个数,特别是在多线程的程序中,经常用它将函数进行包装,然后打包发送给工作线程,让工作线程去执行我们的任务. ...
- std::function,std::bind
std::function 和 std::bind 标准库函数bind()和function()定义于头文件中(该头文件还包括许多其他函数对象),用于处理函数及函数参数.bind()接受一个函数(或者 ...
- std::function,std::bind复习
#include <iostream> #include <functional>//std::bind返回函数对象 void fun1(int a, int b) { std ...
- C++11 std::bind std::function 高级使用方法
从最基础的了解,std::bind和std::function /* * File: main.cpp * Author: Vicky.H * Email: eclipser@163.com */ # ...
- C++ 11 笔记 (四) : std::bind
std::bind 接受一个可调用的对象,一般就是函数呗.. 还是先上代码: void func(int x, int y, int z) { std::cout << "hel ...
- cocos2dx 3.0 它 使用std::bind更换CC_CALLBACK_N
在cocos2dx 3.0 版本号,回调函数本质4一个CC_CALLBACK_N 替换功能.N的回调函数的参数的数量的代表 1.让我们来看看这些CC_CALLBACK_N怎么用 比方action的回调 ...
- std::bind学习
std::bind bind是对C++98标准中函数适配器bind1st/bind2nd的泛化和增强,可以适配任意的可调用对象,包括函数指针.函数引用.成员函数指针和函数对象. bind接受的第一个参 ...
- 第12课 std::bind和std::function(3)_std::function可调用对象包装器
1. std::function (1)首先是一个类模板,用于包装可调用对象.可以容纳除了类成员(函数)指针之外的所有可调用对象. (2)可以将普通函数,lambda表达式和函数对象类统一起来.尽管它 ...
随机推荐
- 《学习之道》第八章孤军奋战or组队合作
孤军奋战与组队合作:别再苦思冥想,拖延行为需要差别对待 对拖延我得提一个小建议,你要暂时把自己与那些会干扰你的人和事隔离开.自己到一个房间里去,或者去图书馆,这样就没什么事能让你分心了. 如果一门课让 ...
- C#学习-接口
众所周知,电脑有拍照和播放光碟的功能. 现在有一个TakingPhoto类,它提供了拍照的功能:还有一个PlayVCD类,它提供了播放光碟的功能. 电脑同时具有着两个类提供的功能,因此我们希望定义一个 ...
- 99%的Linux运维工程师必须要掌握的命令及运用
本为同步于微信公众号[IT行业技术圈]关注即可查看更多相关知识点~ Linux对于程序员来并不陌生,随着图形化界面的深入人心,渐渐地命令行开始淡出了我们的视野,随着时间的推移也变得生疏且陌生起来.在此 ...
- MERGE INTO无法更新ON中的字段解决办法
可以将on里的条件放到update 之后的where条件里 MERGE INTO xshtest.WEB_USER_VIP T1 USING ( select 53254624 enterpriseI ...
- 树莓派开启samba服务
安装samba 和 samba-common-bin 启动树莓派以后,在命令行输入: sudo apt-get update sudo apt-get install samba samba-comm ...
- Django与supervisor 管理进程
1.前言 在Django项目中,我们需要用到一些独立于Django框架外的脚本.这样一些脚本可能需要独立的持续运行,且具有很强的可维护性,这个时候supervisor就可以排上用场了. 基于pytho ...
- c#关键字和常用类型表快查
类型 字节 取值范围 说明 bool 1 true/false/null 布尔类型 char 2 0x0000~0xffff Unicode 16 位字符 byte 1 0~255 无符号的 8 位整 ...
- css Margin-top塌陷,解决方法
在两个盒子嵌套时,内部的盒子设置的margin-top会加到外边的盒子上,导致内部的盒子margin-top设置失败,解决方法如下: (1)外部盒子设置一个边框 (2)外部盒子设置overflow:h ...
- VS2008,System.Runtime.InteropServices.COMException (0x800401F3): Invalid class string (Exception from HRESULT: 0x800401F3 (CO_E_CLASSSTRING))
在VS2008环境中编译调试运行不报错,但在发布的exe文件运行就报错 System.Runtime.InteropServices.COMException (0x800401F3): Invali ...
- SSIS - 1.简介
一.什么是SSIS? 1)SSIS全称为Microsoft SQL Server Integration Services. 2)ETL全称为Extraction, Transformation an ...