美文网首页
参数绑定

参数绑定

作者: 学习编程好少年 | 来源:发表于2017-01-10 11:55 被阅读0次

    对于那种只在一两个地方使用的简单操作,lambda表达式是最有用的。如果我们需要在很多地方使用相同的操作,通常应该定义一个函数,而不是多次编写相同的lambda表达式。类似的,如果一个操作需要很多语句才能完成,通常使用函数更好。

    如果lambda表达式的捕获列表为空,通常可以用函数来代替它。对于捕获局部变量的lambda就需要用到参数绑定。

    标准库bind函数,定义在头文件functional中。可以将bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
    调用bind的一般形式为:

    auto newCallable = bind(callable, arg_list);
    

    其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。即,当我们调用newCallable时,newCallable会调用callable,并传递给它arg_list中的参数。
    arg_list中的参数可能包含形如_n的名字,其中n是一个整数。这些参数是“占位符”,表示newCallable的参数,它们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对象中参数的位置:_1为newCallable的第一个参数,_2为第二个参数,依此类推。

    名字_n都定义在一个名为placeholders的命名空间中,而这个命名空间本身又定义在std命名空间中。可以使用using namespace std::placeholders;使得由placeholders定义的所有名字都可用,与bind函数一样,placeholders命名空间也定义在functional头文件中。

    //举例:g是一个有两个参数的可调用对象。
    auto g = bind(f, a, b, _2, c, _1);
    

    可以使用bind重排参数顺序,举例:

    //按单词长度由短至长排序
    sort(words.begin(), words.end(), isShorter);
    //按单词长度由长至短排序
    sort(words.begin(), words.end(), bind(isShorter, _2, _1) );
    

    默认情况下,bind的那些不是占位符的参数被拷贝到bind返回的可调用对象中。但是,与lambda类似,有时对有些绑定的参数我们希望用引用方式传递,或是要绑定参数的类型无法拷贝。举例:

    ostream &print(ostream &os, const string &s, char c)
    {
        return os << s << c;
    }
    //os是一个局部变量,引用一个输出流
    //错误:不能拷贝os
    for_each(words.begin(), words.end(), bind(print, os, _1, ' ') );
    //正确的做法是:
    for_each(words.begin(), words.end(), bind(print, ref(os), _1, ' ') );
    

    标准库ref函数返回一个对象,包含给定的引用,此对象是可以拷贝的。标准库中还有一个cref函数,生成一个保存const引用的类。与bind一样,函数ref和cref也定义在头文件functiona中。

    旧版本C++提供的绑定函数参数的语言特性限制更多,也更复杂。标准库定义了两个分别名为bind1st和bind2st的函数。类似bind,这两个函数接受一个函数作为参数,生成一个新的可调用对象,该对象调用给定函数,并将绑定的参数传递给它。但是,这些函数分别只能绑定第一个或第二个参数。由于这些函数局限太强,在新标准中已被弃用。所谓被弃用的特性就是在新版本中不再支持的特性。新的C++程序应该使用bind。

    相关文章

      网友评论

          本文标题:参数绑定

          本文链接:https://www.haomeiwen.com/subject/ffukbttx.html