最近在看《深入应用c++11》的时候遇到了std::bind的一些新用法,之前没有遇到过,这里记录下。通常时候std::bind是与std::function一起结合使用的,std::bind是一个函数模板,而std::function是一个类模板,这个从其源码就可看出
/**
* @brief Function template for std::bind.
* @ingroup binders
*/
template<typename _Func, typename... _BoundArgs>
inline typename
_Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type
bind(_Func&& __f, _BoundArgs&&... __args)
{
typedef _Bind_helper<false, _Func, _BoundArgs...> __helper_type;
typedef typename __helper_type::__maybe_type __maybe_type;
typedef typename __helper_type::type __result_type;
return __result_type(__maybe_type::__do_wrap(std::forward<_Func>(__f)),
std::forward<_BoundArgs>(__args)...);
}
template<typename _Signature>
class function;
std::bind的常见用法
之前的理解仅仅是将bind当做绑定一个全局函数,现在又遇到了一些其他的用法,直接上代码吧
/*
* main.cpp
*
* Created on: 2017年12月3日
* Author: Administrator
*/
#include <iostream>
#include <functional>
void output(int x, int y)
{
std::cout << x << " " << y << std::endl;
}
class A
{
public:
int i_ = 0;
void output(int x, int y)
{
std::cout << x << " " << y << std::endl;
}
void operator()() const //无参数 无返回值的仿函数
{
std::cout <<"仿函数"<< std::endl;
}
};
int main(void)
{
//1,绑定全局函数
std::bind(output,1,2); //全局函数,仅仅是绑定,没有调用
std::bind(output,1,2)();//绑定并调用全局函数
//2,绑定成员函数
A a;
std::function<void(int, int)> fr =
std::bind(&A::output, &a /*调用者*/, std::placeholders::_1, std::placeholders::_2);
fr(1, 2); //输出 1 2
//3,绑定成员变量(包括静态的成员变量)
std::function<int&(void)> fr_i = std::bind(&A::i_, &a/*调用者*/); //vs13的bug,绑定成员变量要报错
fr_i() = 123;
std::cout << a.i_ << std::endl; //输出 123
std::cout << fr_i() << std::endl; //输出 123
A a1;
std::function<int&(void)> fr_i_1 = std::bind(&A::i_, a1/*调用者*/); //调用者没有传指针
fr_i_1() = 123;
std::cout << a1.i_ << std::endl; //输出 0
std::cout << fr_i_1() << std::endl; //输出 123
//4,仿函数
std::function<void(void)> op = std::bind(&A::operator(),a);
op();
return 0;
}
结果如下:
1 2
1 2
123
123
0
123
仿函数
另外,bind函数不能绑定重载函数,原因有待深究。
上面代码中,成员函数的入参是函数名,函数名是个指针,因此是取地址;而调用者的话没有要求,如果调用者是值拷贝,会发现实际的对象值还是未改变的,如上面结果中的0。
针对bind函数中的引用是右值引用,这里形参的话又涉及到引用折叠,后续继续研究