using std :: bind

http://www.jellythink.com/archives/773

Let's look at std :: bind1st and std :: bind2nd

bind is a mechanism that can advance to specify certain parameters callable entities bound to existing variable, generate a new callable entity, this mechanism is also quite useful to use the callback function. C ++ 98, there are two functions bind1st and bind2nd, which can be used are the first and second parameters functor of binding, they are only one parameter can be bound. Restrictions, and such availability bind1st bind2nd greatly reduced.

If the content above, you do not understand std :: bind1st and std :: bind2nd in the end is where the Holy Spirit in the end what it is, then look at this code sample:

#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
    vector<int> coll;
    for (int i = 1; i <= 10; ++i)
    {
        coll.push_back(i);
    }

    // 查找元素值大于10的元素的个数
    // 也就是使得10 < elem成立的元素个数 
    int res = count_if(coll.begin(), coll.end(), bind1st(less<int>(), 10));
    cout << res << endl;

    // 查找元素值小于10的元素的个数
    // 也就是使得elem < 10成立的元素个数 
    res = count_if(coll.begin(), coll.end(), bind2nd(less<int>(), 10));
    cout << res << endl;

    return 0;
}

By the above code to understand std :: bind1st and std :: bind2nd yet? Still I do not understand? Well, I went to the small talk.

For the above code, less<int>()in fact, it is a functor, if not std :: bind1st and std :: bind2nd, then we can use the less<int>()following code:

less<int> functor = less<int>();
bool bRet = functor(10, 20); // 返回true

Did you see it? less<int>()This object is the functor requires two parameters, for example 10 <20 compared, then the left argument is called 10, 20 is called the right parameters.

  • When using the std::bind1sttime, it means the left binding parameters, i.e. parameters left unchanged, while the right parameters Element is the corresponding container;
  • When using the std::bind2ndtime, it means bound right parameters, that is right parameters unchanged, while the left parameter is the corresponding container element.

This time should be said to understand.

Let's look at std :: bind

C ++ 11 are provided std::bind. bind () function like its sense of function names, is used to bind certain parameters of the function call.

bind的思想实际上是一种延迟计算的思想,将可调用对象保存起来,然后在需要的时候再调用。而且这种绑定是非常灵活的,不论是普通函数、函数对象、还是成员函数都可以绑定,而且其参数可以支持占位符,比如你可以这样绑定一个二元函数auto f = bind(&func, _1, _2);,调用的时候通过f(1,2)实现调用。

简单的认为就是std::bind就是std::bind1ststd::bind2nd的加强版。

怎么使用std::bind

一个知识点厉不厉害,归根到底还是要经过实践的考验,下面就来看看std::bind到底怎么用。

先看看《C++11中的std::function》中那段代码,std::function可以绑定全局函数,静态函数,但是绑定类的成员函数时,必须要借助std::bind的帮忙。但是话又说回来,不借助std::bind也是可以完成的,只需要传一个*this变量进去就好了,比如:

#include <iostream>
#include <functional>
using namespace std;

class View
{
public:
    void onClick(int x, int y)
    {
        cout << "X : " << x << ", Y : " << y << endl;
    }
};

// 定义function类型, 三个参数
function<void(View, int, int)> clickCallback;

int main(int argc, const char * argv[])
{
    View button;

    // 指向成员函数
    clickCallback = &View::onClick;

    // 进行调用
    clickCallback(button, 10, 123);
    return 0;
}

再来一段示例谈谈怎么使用std::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中std::placeholders的使用。 std::placeholders是一个占位符。当使用bind生成一个新的可调用对象时,std::placeholders表示新的可调用对象的第 几个参数和原函数的第几个参数进行匹配,这么说有点绕。比如:

auto bindFunc3 = bind(TestFunc, std::placeholders::_2, std::placeholders::_3, std::placeholders::_1);

bindFunc3(100.1, 30, 'C');

可以看到,在bind的时候,第一个位置是TestFunc,除了这个,参数的第一个位置为占位符std::placeholders::_2,这就表示,调用bindFunc3的时候,它的第二个参数和TestFunc的第一个参数匹配,以此类推。

以下是使用std::bind的一些需要注意的地方:

  • bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的;
  • 对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。placeholder是pass-by-reference的;
  • bind的返回值是可调用实体,可以直接赋给std::function对象;
  • 对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的;
  • 类的this可以通过对象或者指针来绑定。

为什么要用std::bind

当我们厌倦了使用std::bind1ststd::bind2nd的时候,现在有了std::bind,你完全可以放弃使用std::bind1ststd::bind2nd了。std::bind绑定的参数的个数不受限制,绑定的具体哪些参数也不受限制,由用户指定,这个bind才是真正意义上的绑定。

在Cocos2d-x中,我们可以看到,使用std::bind生成一个可调用对象,这个对象可以直接赋值给std::function对象;在类中有一个std::function的变量,这个std::functionstd::bind来赋值,而std::bind绑定的可调用对象可以是Lambda表达式或者类成员函数等可调用对象,这个是Cocos2d-x中的一般用法。

以后遇到了“奇葩”用法再继续总结了,一次也总结不完的。


发布了17 篇原创文章 · 获赞 22 · 访问量 10万+

Guess you like

Origin blog.csdn.net/u013255206/article/details/70661930