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;
    
    }
    
    
    
     
  • 相关阅读:
    C++ STL list
    1159 Palindrome
    3070 Fibonacci
    1458 Common Subsequence
    git工具之重写历史
    git工具之修订版本(revision)选择
    git工具之使用git调试
    程序员也要听歌啊 写写歌词~(毛不易)《借》《消愁》《像我这样的人》
    git基本命令讲解
    git工作原理
  • 原文地址:https://www.cnblogs.com/KunLunSu/p/7967428.html
Copyright © 2011-2022 走看看