zoukankan      html  css  js  c++  java
  • C++ 中std::function 、std::bind的使用和lambda的使用

    1. std::function是可调用对象的包装器;std::bind是将可点用对象和其参数一起进行绑定,且绑定后的结果可以使用std::function对象进行保存,并延迟调用到需要调用的时候;
    2. 在C++中,可调用实体主要包括函数,函数指针,函数引用,可以隐式转换为函数指定的对象,或者实现了opetator()的对象(即C++98中的functor)。C++0x中,新增加了一个std::function对象,std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(我们知道像函数指针这类可调用实体,是类型不安全的)。
    3. bind是这样一种机制,它可以预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调用实体,这种机制在回调函数的使用过程中也颇为有用。C++98中,有两个函数bind1st和bind2nd,它们分别可以用来绑定functor的第一个和第二个参数,它们都是只可以绑定一个参数。各种限制,使得bind1st和bind2nd的可用性大大降低。C++0x中,提供了std::bind,它绑定的参数的个数不受限制,绑定的具体哪些参数也不受限制,由用户指定,这个bind才是真正意义上的绑定,有了它,bind1st和bind2nd就没啥用武之地了,因此C++0x中不推荐使用bind1st和bind2nd了,都是deprecated了。
    4. C++11 的 lambda 表达式规范如下:

      [ capture ] ( params ) mutable exception attribute -> ret { body } (1)  
      [ capture ] ( params ) -> ret { body } (2)  
      [ capture ] ( params ) { body } (3)  
      [ capture ] { body } (4)  

      其中

      • (1) 是完整的 lambda 表达式形式,
      • (2) const 类型的 lambda 表达式,该类型的表达式不能改捕获("capture")列表中的值。
      • (3)省略了返回值类型的 lambda 表达式,但是该 lambda 表达式的返回类型可以按照下列规则推演出来:
        • 如果 lambda 代码块中包含了 return 语句,则该 lambda 表达式的返回类型由 return 语句的返回类型确定。
        • 如果没有 return 语句,则类似 void f(...) 函数。
      • 省略了参数列表,类似于无参函数 f()。

      mutable 修饰符说明 lambda 表达式体内的代码可以修改被捕获的变量,并且可以访问被捕获对象的 non-const 方法。

      exception 说明 lambda 表达式是否抛出异常(noexcept),以及抛出何种异常,类似于void f(throw(X, Y)。

      attribute 用来声明属性。

      另外,capture 指定了在可见域范围内 lambda 表达式的代码内可见得外部变量的列表,具体解释如下:

      • [a,&b] a变量以值的方式呗捕获,b以引用的方式被捕获。
      • [this] 以值的方式捕获 this 指针。
      • [&] 以引用的方式捕获所有的外部自动变量。
      • [=] 以值的方式捕获所有的外部自动变量。
      • [] 不捕获外部的任何变量。

      此外,params 指定 lambda 表达式的参数。

    5. 测试用例:

        1、std::function作为回调函数使用示例

        

    class A
    {
    std::function<void()> callback_;
    public:
    A(const std::function<void()>& f) :callback_(f){}
    void Notify()
    {
    callback_();
    }
    };
    class Foo
    {
    public:
    void operator()(void)
    {
    std::cout << __FUNCTION__ << std::endl;//get the func name
    
    }
    };
    void Test8()
    {
    Foo foo;
    A a(foo);
    a.Notify();
    }

      2、std::function 和std::bind 结合使用:

    void call_when_event(int x, const std::function<void(int)>& func)
    {
        if (!(x & 1))
        {
            //cout << x << endl;
            func(x);
        }
    }
    
    void call_when_event1(int x,int y, const std::function<void(int,int)>& func)
    {
        if (!(x & 1))
        {
            //cout << x << endl;
            func(x,y);
        }
    }
    void output(int x)
    {
        cout << x << endl;
    }
    void output_add_2(int x,int y)
    {
        cout << x + y << endl;
    }
    void Test7()
    {
        auto fr = std::bind(output, std::placeholders::_1);
        for (int i = 0; i < 10; i++)
        {
            call_when_event(i, fr);
        }
        std::cout << std::endl;
    
        auto fr1 = std::bind(output_add_2, std::placeholders::_1,std::placeholders::_2);
        for (int i = 0; i < 10; i++)
        {
            call_when_event1(i, i,fr1);
        }
    }
    3、lambda 测试用例:
    返回vector中大于5小于10的元素的个数:
    void Test5()
    {
        std::vector<int> coll;
        for (int i = 0; i <= 10; i++)
        {
            coll.push_back(i);
        }
        int count = std::count_if(coll.begin(), coll.end(), [](int x){return x > 5 && x < 10; });
        std::cout << count << std::endl;
    
    }
    
    
    
     
  • 相关阅读:
    Codeforces467C George and Job
    Codeforces205E Little Elephant and Furik and RubikLittle Elephant and Furik and Rubik
    Codeforce205C Little Elephant and Interval
    51nod1829 函数
    51nod1574 排列转换
    nowcoder35B 小AA的数列
    Codeforce893E Counting Arrays
    gym101612 Consonant Fencity
    CodeForces559C Gerald and Giant Chess
    CodeForces456D A Lot of Games
  • 原文地址:https://www.cnblogs.com/KunLunSu/p/7967428.html
Copyright © 2011-2022 走看看