简述泛型算法之 三bind_参数绑定
来源:互联网 发布:潭州学院java视频下载 编辑:程序博客网 时间:2024/05/16 14:29
简述泛型算法之 三bind 参数绑定
lambda不足
在上篇博客简述泛型算法之 二lambda表达式中提到lambda有不足之处。何以见得?
1) 对于那种只在一两个地方使用的简单操作,lambda表达式是最有用的。但如果我们要在多处使用相同的算法,通常应该定义一个函数,而不是编写相同的lambda表达式。
2)如果一个操作需要很多语句完成,通常使用函数会更好。
如果lambda的捕获列表为空,则用函数代替很容易;
但如果对于捕获函数列表的lambda,用函数代替就不容易了。
我们围绕一个问题详细展开:
ex:比较一个string和一个给定大小
bool check_size(const string& s, string::size_type sz) { return s.size() >= sz;}
用lambda表达式很容易实现:
find_if(v.begin(), v.end(), [sz](const string& s) { return s.size() >= sz; });
但用函数却不行,因为无法向算法传递一个参数。为了用check_size代替lambda,则必须解决如何向sz形参传递一个参数的问题。
标准库函数bind
bind是一个通用的函数适配器(function adaptor),接受一个可调用对象,生成一个新的可调用对象来适应元对象的参数列表。
---进入关键地带了--(摘自候捷STL源码剖析)
bind一般形式
auto new_callable = bind(callable, arg_list);
1) new_callable本身是一个可调用对象,arg_list时参数列表,对应callable中的参数。即,当我们调用new_callable时,new_callable会调用callable,并传递给它arg_list中的参数。
2) arg_list中参数可能包含形如_n的名字,n是一个整数。这些参数是“占位符”,表示new_callable的参数。数值n表示生成的可调用对象中参数的位置:_1为new_callable的第一个参数,,,
绑定check_size的sz参数
对于该函数:
bool check_size(const string& s, string::size_type sz) { return s.size() >= sz;}
使用bind来生成一个调用check_size的对象; auto check_sz = bind(check_size, _1, sz);
此处,我们可以直接调用check_sz
string s = "hello";bool b1 = check_sz(s);
结合find_if使用: find_if(v.begin(), v.end(), bind(check_size, _1, sz));
使用placeholder名字
名字_n都定义在一个名为placeholder的命名空间中,而这个命名空间又定义在std中;为了使用这些命名空间,两者都要写上;
ex:对于_1的using声明:
using std::placeholders::_1
标准库规定,对于每个占位符,都必须提供一个单独的声明;这样很繁琐,为了简单且不易出错,可以用另一种形式的using语句:
using namespace std::placebolders;
bind的参数
1) 可以用bind绑定给定可调用对象中的参数
ex:假定f可调用,有5个参数 auto g = bind(f, a, b, _2, c, _1);
生成一个可调用对象,它有两个参数分别用占位符_2,_1表示。 g(_1, _2)
将会映射为: f(a, b, _2, c, _1);
例如:调用g(x, y)会调用
f(a, b, y, c, x);
解析:
占位符的总个数即为new_calloable接受的参数的个数:用n(此处是2)表示;
因为bind中有两个占位符,因此,在调用bind生成的可调用对象时,要传递给它两个参数。
占位符数值i对应于new_callable中的第i个参数
对于bind中’_2’处于参数列表中第三个位置,因为是2,所以绑定到g(x, y)中的第二个参数;
因此,f中第三个位置的参数对应于g中的第2个参数;
2) 可以用bind重新安排其顺序
可以用bind颠倒compare的含义:
bool compare_1(const int a, const int b) { return a < b;}//由短至长排序sort(v.begin(), v.end(), compare);//由长至短排序sort(v.begin(), v.end(), bind(compare, _2, _1));
绑定引用参数
默认情况下,bind绑定的那些 不是占位符的 参数被拷贝到bind返回的可调用对象中,但是与lamda类似,有时对绑定的参数希望用引用的方式传递,或者有些参数无法拷贝;
ex:
vector<string> v{"tx", "bd", "al", "ms", "ne"};ostream& os(cout);for_each(v.begin(), v.end(), [&os, c] (const string& s) { os << s << c;});
可以很容易编写函数,完成相同的工作:
ostream& print(ostream& os, const string& s, char c) { return os << s << c;}
但不能直接用bind代替对os的捕获;
//错误代码 for_each(v.begin(), v.end(), bind(print, os, _1, ' '));
因为bind拷贝其参数,而ostream类型无法拷贝。
如果我们希望传递给bind一个对象而又不拷贝,就必须使用标准库函数ref函数.
//正确代码for_each(v.begin(), v.end(), bind(print, ref(os), _1, ' '));
标准库还有一个cref函数,生成一个保存const引用的类。与bind一样,ref和cref都定义在头文件functional中。
向后兼容:参数绑定
STL源码剖析中提到的参数绑定时bind1st和bind2nd函数,类似bind,这两个函数接受一个函数作为参数生成一个新的可调用对象。但这些函数分别只能绑定第一个或者第二个参数。由于这些函数局限性太强,新标准中已经被废弃。因此,新的C++程序应该使用bind函数。
- 简述泛型算法之 三bind_参数绑定
- 简述泛型算法之 一认识算法
- 简述泛型算法之_二lambda表达式
- hibernate之参数绑定
- hibernate之参数绑定
- SpringMvc之参数绑定
- STL总结之算法简述
- 值 之三 绑定
- C++泛型算法之向算法传递参数
- hibernate查询之参数绑定
- SpringMVC之数据参数绑定
- Spring MVC 之 参数绑定
- SSM整合之参数绑定
- C++三大特性之继承简述
- Spring boot(三):@RequestMapping之Form表单参数传递及POJO绑定实例讲解
- 三、SpringMVC常用注解、参数绑定
- springmvc(三)---方法参数绑定
- java泛型之三——参数泛型上下限
- 用面向对象的思维去解决数三退一。关键字,双向环形链表。
- day11 JSP和EL的入门,两个会话技术:cookies和session
- C# 已知圆心和两点,用DrawArc()画圆弧(算法)
- 银线蕨-我的啊银
- 红眼病
- 简述泛型算法之 三bind_参数绑定
- 总结Cocos2d-x 3.0 中新字体标签Label
- 跟着9张思维导图学习Javascript
- 2016-3-28--C#的is和as操作符
- hihocoder 1285 智力竞赛 (类多重背包)
- Easyx图形库的安装及创建项目
- Python 常用编程方法
- 正则表达式
- 亲测解决Genymotion的Unable to load VirtualBox Engine问题