标准库提供用于简化使用函数对象的繁杂的过程的类和函数
为什么是函数对象
可以把一个函数和一个值捆绑到单个实体中
- 如果把值n放到具有一个文件作用域(file scope)的变量中也可以使用函数
|
|
- 不方便
标准库提供
调用:
transform(a, a+100, a, bind1st(plus<int>(), n));
bind1st(plus<int>(), n)
使用标准库创建了一个函数对象
用于內建操作符的函数对象
- plus是一个类型
plus<int>()
是一个等价于类型为plus的匿名对象的表达式- 把两个类型为int的值相加,以和作为结果
|
|
- 三个类型成员
- first_argument_type
- second_argument_type
- result_argument_type
标准库包含內建操作符所需要的绝大部分函数对象
绑定者(Binders)
- 创建能够记住一个值并把该值加到参数上的函数对象
- bind1st和bind2nd库模板函数
bind1st创建一个函数对象,绑定函数的第一个参数
函数对象
bind1st(f, x)
只接受一个参数- f有接受两个参数的
operator()
- f有接受两个参数的
- x是可以作为f的第一个参数的值
(bind1st(f, x))(y)
和f(x, y)
相同的值bind1st(plus<int>(), n)(y)
等价于n+y
|
|
- b的类型?
sometype b = bind1st(p, n);
->binder1st<plus<int> > b = bind1st(p, n)
p是一个函数对象,负责把两个数相加
- b是一个函数独享,负责把n绑定在两个被相加的数的第一个数上
深入探讨
- 写bind1st的声明
|
|
- 约定遵循类型规定的类才能使用binder1st
- first_argument_type
- second_argument_type
- result_argument_type
|
|
接口继承
- C++库如模板类plus的函数对象类都定义了成员类型first_argument_type、second_argument_type和result_type
- 具有共同的基类: binary_function
|
|
- plus定义
|
|
- 标准库的unary_function基类
|
|
- 可以作为negate的基类
|
|
使用这些类
- 标准库容器c,x是某个放在其中的值
find(c.begin(), c.end(), x);
- 生成一个指向c中第一个x相等的迭代器或逾尾迭代器(找不到x)
使用函数配接器以更精巧的方法
find_if(c.begin(), c.end(), bind1st(equal_to<c::value_type>(), x));
- 约定了所有库容器用名为value_type的成员类型表示元素的类型
想知道是否每个元素e都存在
e > x
,采用bind2ndfind_if(c.begin(), c.end(), bind2nd(greater<c::value_type>(), x));
容器x和w具有相同个数的元素
transform(v.begin(), v.end(), w.begin(), v.begin(), plus<v::value_type>());
- 将相应元素相加,结果存放到第四个参数指向开始位置的序列中
找出每个指向包含”C”的以null结尾的字符串的指针并用指向字符串”C++”的指针替换
char* p[N];
replace_if(p, p+N, not1(bind2nd(ptr_fun(strcmp), "C")), "C++");
- ptr_fun创建一个适合于传递给strcmp的函数对象
- bind2nd使用这个对象创建另一个函数对象: 用”C”和它的参数进行比较
- not1否定判断的意义
Summary
这些程序不比相应的常规程序运行得慢
理论上可以更快: 标准库的一部分,编译器在适当的时候可以识别并产生高效的代码
使得一次处理整个容器成为现实,不必采用循环逐个处理单个元素
《C++沉思录(Cplusplus Thinking)》笔记