目录
  • 旧标准的缺陷
    • 繁杂的调用对象
    • 问题浮出水面
  • std::function
    • 小试牛刀
  • std::bind
    • 作用
    • 占位符
    • 高级用法
  • 配合使用

    旧标准的缺陷

    学习新标准的语法之前,先来聊聊旧标准存在的缺陷,这样就可以理解为什么要在C++11中存在std::funtionstd::bind了,这就是所谓——知其然,并知其所以然

    繁杂的调用对象

    C++中可以调用的对象有很多,包括但不限于以下:

    • 函数指针
    • 仿函数(重载了"( )" 运算符)
    • 可被转换为函数指针的类对象
    • 类成员函数

    问题浮出水面

    这些调用对象在使用的时候具有比较统一的时候,但是定义的方式却是五花八门。因此,C++11中为了改善这个问题,提供了std::functionstd::bind来解决

    std::function

    std::function是可调用对象的包装器本质上是一个类模板可容纳除了类成员(函数)指针之外的所有可调用对象

    小试牛刀

    #include<iostream>
    #include<functional>
    class A
    {
    std::function<void()> callback_;
    public:
    A(const std::function<void()>& f) : callback_(f){}
    void notify(void){
    callback_(); //调用这个回调对象
    }
    };
    class Foo{
    public:
    void operator()(void){
    std::cout << __FUNCTION__ << std::endl;
    }
    };
    int main(void)
    {
    Foo foo;
    A aa(foo);
    aa.notify(); //调用这个回调
    return 0;
    }
    //输出
    //operator()

    std::function因为有着保存函数并可以延迟执行的特性,因此非常适合作为回调函数来使用

    std::bind

    std::bind用来将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function进行保存,并延迟调用

    作用

    • 将可调用对象与其参数一起绑定成一个仿函数
    • 将N元可调用对象转换成一元或N-1元可调用对象,即只绑定部分参数

    占位符

    std::bind可以将函数及其参数进行绑定,那么参数的位置与传入的位置相关,因此有了占位符的概念,例如std::placeholders::_1是第一个参数的占位符,当函数传入第一个参数的时候,就会把其进行替换,同理std::palceholders::_2是第二个占位符。

    #include<iostream>
    #include<functional>
    void output(int x, int y){
    std::cout << x << " " << y << std::endl;
    }
    int main(){
    std::bind(output, 1, 2)(); //输出:1 2
    std::bind(output, std::placeholders::_1)(1); //输出:1
    std::bind(output, 2, std::placeholders::_2)(1,2); //输出:2 2
    std::bind(output, std::placeholders::_2, std::placeholders::_1)(1, 2); //输出:2 1
    }

    高级用法

    可以使用std::bind进行多个函数的组合,例如找出集合中大于5小于10的元素个数:

    #include<iostream>
    #include<functional>
    using std::placeholders::_1;
    auto f = std::bind(std::logical_and<bool>(), std::bind(std::greater<int>(), _1, 5),std::bind(std::less_equal<int>(), _1, 10)); //将两个函数参数绑定并进行组合
    int count = std::count_if(coll.begin(), coll.end(), f); //使用

    配合使用

    std::bindstd::function配合使用非常的强大

    #include<iostream>
    #include<funcational>
    class A{
    public:
    int i_ = 0;
    void output(int x, int y){
    std:cout << x << " " << y << std::endl;
    }
    };
    int main(void){
    A a;
    std::function<void(int, int)> fr = std::bind(&A::output, &a, std::placeholders::_1,std::palceholders::_2); //注意
    fr(1, 2); //输出:1 2
    std::function<int&(void)> fr_i = std::bind(&A::i, &a);
    fr_i() = 123;
    std::cout << a.i_ << std::endl; //输出:123
    }

    可以看到上面std::bind在绑定类的成员函数的时候,需要把&a也传进去,这是因为成员函数编译器在使用的时候会自动传入一个this指针,所以我们绑定的时候需要额外传一个对象的地址

    声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。