C++11 std::bind(),std::function,std::ref(),std::cref

std::bind

std::bind可以预先把某个可调用对象的某些参数绑定到已有的变量,产生一个新的可调用对象。bind本身是一种延迟计算的思想,它本身可以绑定普通函数、全局函数、静态函数、类静态函数甚至是类成员函数。bind最终将会生成一个可调用对象,这个对象可以直接赋值给std::function对象,而std::bind绑定的可调用对象可以是Lambda表达式或者类成员函数等可调用对象。

使用方式:bind(&要调用的函数,&对象, 要调用函数的参数1,要调用函数的参数2…,_1(bind函数的参数1),_2(bind函数的参数2)…)

#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, placeholders::_1, 'A', 10.1); //表示绑定函数TestFunc的第二、三个参数分别为'A'和10.1,第一个参数由调用bindFunc1的第一个参数来指定
    bindFunc1(10);   //输出为:10  A  10.1
 	bindFunc1(10,'C'); //输出为:10  A  10.1,已经绑定的值无法通过传参改变
    cout << "=================================\n";
 
    auto bindFunc2 = bind(TestFunc, std::placeholders::_2, placeholders::_1, 10.1);
    bindFunc2('B', 10);   //输出为:10  B  10.1
 
    cout << "=================================\n";
 
    auto bindFunc3 = bind(TestFunc, std::placeholders::_1, placeholders::_2, 10.1);
    bindFunc3(10, 'B');   //输出为:10  B  10.1
 
    return 0;
}

其中placeholders::_1是占位符,用于接收以后的传参。如第二个bindFunc2 函数来说,std::placeholders::_2, 表示现在的第一个入参传入原函数的第二个参数。

注:bind对于不事先绑定的参数,通过std::placeholders传递的参数是通过引用传递的;对于事先绑定的函数参数是通过值传,可以通过std::ref();std::cref来绑定函数参数通过引用传递

bind使用形式:

(1)bind(&f ,arg_1,…) 假设f是一个全局函数,绑定全局函数并调用;后面f后面跟参数事先绑定,不事先绑定的参数,通过std::placeholders传递。

(2)bind (&A::f, A(),arg_1,…) 假设A是一个构造函数为空的类,这个形式绑定了类的成员函数,故第二个参数需要传入一个成员
(成员静态函数除外);

(3)bind (&A::f, _1,arg_1,…)(new A()) 同上,效果是一样的,但是使用了占位符,使得没有固定的的对象,推荐。

注:使用的时候一定要注意指向的是没有this指针的函数(全局函数或静态成员函数),还是有this指针的函数。
后面一种必须要用bind()函数,而且要多一个参数,因为静态成员函数与非静态成员函数的参 数表不一样,原型相同的非静态函
数比静态成员函数多一个参数,即第一个参数this指针,指向所属的对象,任何非静态成员函数的第一个参数都是this指针。

std::function

可以理解为函数指针。C++中把函数指针封装成了一个类,这也正是C++中无处不类的思想的体现,即
std::function,且是模板类。
看实例就比较清楚的了解了

#include <functional>
#include <iostream>
using namespace std;
 
std::function< int(int)> Functional;
 
// 普通函数
int TestFunc(int a)
{
    return a;
}
 
// Lambda表达式
auto lambda = [](int a)->int{ return a; };
 
// 仿函数(functor)
class Functor
{
public:
    int operator()(int a)
    {
        return a;
    }
};
 
// 1.类成员函数
// 2.类静态函数
class TestClass
{
public:
    int ClassMember(int a) { return a; }
    static int StaticMember(int a) { return a; }
};
 
int main()
{
    // 普通函数
    Functional = TestFunc;
    int result = Functional(10);
    cout << "普通函数:"<< result << endl;
 
    // Lambda表达式
    Functional = lambda;
    result = Functional(20);
    cout << "Lambda表达式:"<< result << endl;
 
    // 仿函数
    Functor testFunctor;
    Functional = testFunctor;
    result = Functional(30);
    cout << "仿函数:"<< result << endl;
 
    // 类成员函数
    TestClass testObj;
    Functional = std::bind(&TestClass::ClassMember, testObj, std::placeholders::_1);
    result = Functional(40);
    cout << "类成员函数:"<< result << endl;
 
    // 类静态函数
    Functional = TestClass::StaticMember;
    result = Functional(50);
    cout << "类静态函数:"<< result << endl;
 
    return 0;
}

std::ref();std::cref

std::ref 用于包装按引用传递的值。
std::cref 用于包装按const引用传递的值。

在bind中已经知道事先绑定的值是不使用引用而是传参的,因为bind()不知道生成的函数执行的时候,传递进来的参数是否还有效。std::ref和std::cref就派上用场了。

#include <functional>
#include <iostream>

void f(int& n1, int& n2, const int& n3)
{
    std::cout << "In function: n1[" << n1 << "]    n2[" << n2 << "]    n3[" << n3 << "]" << std::endl;
    ++n1; // 增加存储于函数对象的 n1 副本
    ++n2; // 增加 main() 的 n2
    //++n3; // 编译错误
    std::cout << "In function end: n1[" << n1 << "]     n2[" << n2 << "]     n3[" << n3 << "]" << std::endl;
}

int main()
{
    int n1 = 1, n2 = 1, n3 = 1;
    std::cout << "Before function: n1[" << n1 << "]     n2[" << n2 << "]     n3[" << n3 << "]" << std::endl;
    std::function<void()> bound_f = std::bind(f, n1, std::ref(n2), std::cref(n3));
    bound_f();
    std::cout << "After function: n1[" << n1 << "]     n2[" << n2 << "]     n3[" << n3 << "]" << std::endl;
}

运行结果

Before function: n1[1]     n2[1]     n3[1]
In function: n1[1]    n2[1]    n3[1]
In function end: n1[2]     n2[2]     n3[1]
After function: n1[1]     n2[2]     n3[1]
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值