C++11的bind函数

参数绑定

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

#include <functional>

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。

posted @ 2020-06-09 00:23  WindSun  阅读(751)  评论(0编辑  收藏  举报
博客已停更,文章已转移,点击访问