zoukankan      html  css  js  c++  java
  • C++11的bind函数

    参数绑定

    如果一个函数只在一两个地方操作,使用Lambad很方便,如果在很多地方操作,编写多次相同的Lambda函数就很不方便,需要定义函数。但是,定义的函数又不能完全代替能捕捉局部变量的Lambda函数,所以就出现了bind函数。
    bind函数是C++11标准库的函数,需要添加头文件

    #include <functional.h>
    

    bind就是一个通用的函数适配器,它可以接受一个可调用函数,生成一个新的可调用对象来“适应”原函数的参数列表。

    std::bind函数

    调用bind函数的方式为:

    auto newCallable = bind(callable, arg_list);
    

    说明:
    callable : 本身就是一个可调用的函数
    arg_list : 用逗号分割的参数列表,对应给定的callable参数

    当我们调用newCallable时,会调用callable函数,并且将arg_list的参数传递给callable函数。

    参数占位符

    arg_list中有许多占位符,形如_n的名字,其中n是一个整数,表示newCallable的参数的位置比如:_1为newCallable的第一个参数,_2为第二个参数...。

    举例说明:
    现在有一个函数:

    bool checkSize(const string &s, string::size_type sz)
    {
        return s.size() >= sz;
    }
    

    使用bind生成一个调用checkSize的对象:

    auto check = bind(checkSize, _1, 6);
    

    其中的_1表示需要给第一个参数传递一个const string&。

    string s = "hello";
    bool b1 = check(s); //check(s) 会调用checkSize(s, 6)
    

    使用bind,可以将原来的基于Lambda的find_if调用:

    auto wc = find_if(words.begin(), words.end(), [sz](const string &a));
    

    改变为使用checkSize版本:

    auto wc = find_if(words.begin(), words.end(), bind(check_size, _1, sz));
    

    _n参数说明

    \_n参数都定义在一个名字为placeholders命名空间中,这个命名空间又在std命名空间中。那么\_1就是:

    using std::placeholders::_1;
    

    对每一个占位符都要使用using声明,非常麻烦,可以使用:

    using namespace std::placeholders;
    

    placeholders的明明空间也定义在functional.h头文件中

    bind的参数顺序

    bind绑定的给定函数的参数的顺序。比如func是一个函数,它有5个参数,下面对bind的调用:

    auto g = bind(fun, a, b, _2, c, _1);
    

    生成一个新的可调用对象,有两个占位符,传递给g的第一个参数绑定到_1,第二个参数绑定到_2,bind调用会将g(_1, _2)映射为f(a, b, _2, c, _1),如:调用g(X, Y)就会调用f(a, b, Y, c, X);

    绑定引用参数

    默认情况下,bind的非占位符的参数是拷贝到bind返回的可调用的函数中,与Lambda类似,有时候绑定的参数希望用引用的方式传递,或不让绑定的参数类型拷贝。
    例如:

    for_each(words.begin(), words.end(), [&os, c](const string &s) {os << s << c;});
    

    可以编写一个函数完成同样的功能:

    ostream &print(ostream &os, const strint &s, char c)
    {
        return os << s << c;
    }
    

    但是:不能直接用bind来代替os的捕获:

    for_each(words.begin(), words.end(), bind(print, os, _1, ' ');
    

    由于不能拷贝一个ostream。如果我们希望bind一个函数而不希望拷贝参数,就需要用标准库的ref函数。

    for_each(words.begin(), words.end(), bind(printf, ref(os), _1, ' '));
    

    函数ref返回一个对象,包含给定的引用,此对象是可以拷贝的。标准库中还有cref函数,生成一个保存const引用的类。ref和cref都在头文件"functional.h"

    关于bind1st和bind2nd函数

    标准库中定义了这两个函数,类似于bind,但是这两个函数只能分别绑定第一个或第二个参数。由于局限性太强,在C++11中已经被弃用,新的C++应该使用bind。

  • 相关阅读:
    python-套接字编程之udp
    python-套接字编程之tcp
    用脚本获取windows的mac地址
    电脑控制安卓手机(手机投屏)
    人体内脏分布图
    电子发票打印出来太大了,怎么办?
    局域网内搭建各部门文件共享
    樊登读书会:《善战者说:孙子兵法与取胜法则十二讲》
    健康饮食——百万教程
    减肥十律
  • 原文地址:https://www.cnblogs.com/WindSun/p/13069887.html
Copyright © 2011-2022 走看看