zoukankan      html  css  js  c++  java
  • (原创)C++11改进我们的程序之简化我们的程序(五)

    这次要讲的是:c++11中的bind和function

    std::function

    它是函数、函数对象、函数指针、和成员函数的包装器,可以容纳任何类型的函数对象,函数指针,引用函数,成员函数的指针。
    以统一的方式处理函数、函数对象、函数指针、和成员函数。
    允许保存和延迟执行函数。

    • 函数和成员函数作为function
    void G();
    struct A
    {
    void H(){}
    };
    
    std::function<void()> f = G; //全局函数
    
    A a;
    std::function<void()> f 1= std::bind(&A::H, a); //成员函数
    • 可以用function取代函数指针。因为它可以保存函数延迟执行,所以比较适合作为回调函数,也可以把它看做类似于c#中特殊的委托,只有一个成员的委托。
    struct A
    {
    A(std::function<void()>& f):m_callback(f)
    void Notify()
    {
    m_callback();//回调到上层
    }
    
    std::function<void()> m_callback;
    }
    • function还可以作为函数入参,这样可以在函数外部控制函数的内部行为了,让我们的函数变得更加灵活。
    void Foo(int x, std::function<void(int)>& f)
    {
    if(x%2==0)
    f(x);
    }
    
    void G(int x)
    {
    cout<<x<<endl;
    }
    
    void H(int x)
    {
    cout<<x+2<<endl;
    }
    
    void TestFoo()
    {
    auto f = std::bind(G, std::placeholders::_1); 
    Foo(4, f);
    
    //在Foo函数外面更改f的行为
    f = std::bind(H, std::placeholders::_1);
    Foo(4, f);
    }

    std::bind绑定器

    • 将函数、成员函数和闭包转成function函数对象
    • 将多元(n>1)函数转成一元函数或者(n-1)元函数。
    void H(int a);
    //绑定全局函数
    auto f11 = std::bind(H, std::placeholders::_1);
    auto的类型实际上是std::function<void(int)>
    
    //绑定带参数的成员函数
    std::function<void (char*, int)> f = std::bind(&ReadHandler::ConnectPreProcess, this, std::placeholders::_1, std::placeholders::_1);
    
    //三元函数转换成一元函数
    int f(int, char, double);
    // 绑定f()函数调用的第二个和第三个参数,
    // 返回一个新的函数对象为ff,它只带有一个int类型的参数
    auto ff = bind(f, _1, ‘c’, 1.2);    
    int x = ff(7); 
    • bind简化和增强bind1st和bind2nd

      其实bind简化和增强了之前标准库中bind1st和bind2nd,它完全可以替代bind1s和bind2st,并且能组合函数。我们知道bind1st和bind2nd将一个二元算子转换成一个一元算子。

    //查找元素值大于10的元素的个数
    int count = count_if(coll.begin(), coll.end(), std::bind1st(less<int>(), 10));
    //查找元素之小于10的元素
    int count = count_if(coll.begin(), coll.end(), std::bind2nd(less<int>(), 10));

      本质上是对一个二元函数less<int>的调用,但是它却要分别用bind1st和bind2nd,而且还要想想到底是用bind1st还是bind2nd,用起来感觉不方便。现在用bind,就可以以统一的方式去实现了。

    //查找元素值大于10的元素的个数
    int count = count_if(coll.begin(), coll.end(), bind(less<int>(), 10, _1));
    //查找元素之小于10的元素
    int count = count_if(coll.begin(), coll.end(), bind(less<int>(), _1, 10));
    这样我就不用关心到底是用bind1st还是bind2nd了,只要用bind就都搞定了。
    • bind函数组合

    bind的还有一个强大之处就是函数组合。假设我们要找出集合中大于5小于10的元素个数怎么做呢?我们需要一个逻辑与才能做到类似于:

    std::bind(std::logical_and<bool>(),_1,_2);

    然后,我们需要另一个谓词来回答 _1 是否大于5。

    std::bind(std::greater<int>(),_1,5);

    然后,我们还需要另一个谓词来回答 _1 是否小于等于10。

    std::bind(std::less_equal<int>(),_1,10);

    最后,我们需要把它们两个用逻辑与合起来,就象这样:

    //查找集合中大于5小于10的元素个数
    auto f = bind(std::logical_and<bool>(), bind(std::greater<int>(),_1,5), bind(std::less_equal<int>(),_1,10));
    int count = count_if(coll.begin(), coll.end(), f);

      c++11中推出function是为了泛化函数对象,函数指针,引用函数,成员函数的指针,让我们可以按更统一的方式写出更加泛化的代码;推出bind是为了替换和增强之前标准库的bind1st和bind2st,让我们的用起来更方便!

    c++11 boost技术交流群:296561497,欢迎大家来交流技术。

  • 相关阅读:
    监督学习
    第一个应用:鸢尾花分类
    第一章 计算机系统漫游
    前言
    python批量下载验证码,用来做验证码处理
    windows下安装tesserocr
    python 爬虫之requests爬取页面图片的url,并将图片下载到本地
    electron实现透明点投的方法
    css之实现下拉框自上而下展开动画效果&&自下而上收起动画效果
    react项目中canvas之画形状(圆形,椭圆形,方形)
  • 原文地址:https://www.cnblogs.com/qicosmos/p/3302144.html
Copyright © 2011-2022 走看看