可调用对象
//仿函数是一个类的对象,这个对象 具有函数的功能 (函数对象)
bool MyComp(int x, int y)
{
//return x > y;
return false;
}
template<typename T>
class _less
{
public:
bool operator ()(T& a, T& b)
{
return a < b;
}
};
void TestSort()
{
list<int> iList({ 1, 4, 7, 8, 5, 3, 2, 9, 6 });
list<int>::iterator it;
//iList.sort();//对 iList进行升序排列
//如果我们自己定义排序函数
iList.sort(MyComp);// 变成了降序排列
//我们的排序函数,其实是一个模板函数,有一个模板参数 _Pr 代表排序规则
//我们要实现排序,无非是在里面判断 a[i] < a[j]
//如果判断改成 a[i] > a[j] --》排序方式就变了
//我们这个 a[i] < a[j] 在这个 sort函数里面,就调用了 _Pr(a[i], a[j])
//--> sort 这个模板函数,_Pr 的默认值是 less<T>()
//less<T>() 就是一个仿函数
//-->less 是一个模板类 ---》less<T> 生成一个具体类
//-->less<T>() 生成一个对象,这个对象,就是仿函数 (具有函数功能)
//--》判断是否 a<b : ret = less<int>()(a, b)
//--》我们传入 一个函数指针或者仿函数 MyComp, 可以理解为我们重新定义了 < 符号
//如果 MyComp 不写 return a > b 或者 a < b
//我们分别写return true, return false
//return true --》出错
//return false --》正常
//我们之前讲过一个知识点:< 定义好了后, 所有的逻辑比较就都确定了
//因为 >, >=, <=, ==, != 都可以用 < 符号表示出来
// > 符号使用 < 符号表示出来:a > b --> 我们可以写成 b < a
// >=符号使用 < 符号表示出来:a >= b --> 我们可以写成 !(a < b)
// <=符号使用 < 符号表示出来:a <= b --> 我们可以写成 !(b < a)
// ==符号使用 < 符号表示出来:a == b --> 我们可以写出 !(a < b) && !(b < a) [a既不大于b,也不小于b]
// !=符号使用 < 符号表示出来:a != b --> 我们可以写成 (a < b) || (b < a)
//接下来我们再看 MyComp(int x, int y) {return false;}
// 也就是对 任意 x 和 y ===> x < y 的结果都是 false
// x,y 是任意的,把他们交换一下也成立 ==> y < x 也是false
// 也就是对任意两个数 x ,y。x 既不大于y,也不小于y,==》 x == y
// --> 也就 == 符号的推导,它的结果 恒为 true
// --》 所以我们定义这个比较规则,就是说,我们定义所有数都相等
// --》 所以 使用 return false 排序结果是 维持序列不变 (所有元素相等,已经排好序了)
//再来看 MyComp(int x, int y) {return true;}
//为什么会出错呢?
//因为我们由这个可以推出 a!=a , 自相矛盾!
// 我们看 != 符号的表示 (a < b) || (b < a) ==》恒为 true
// 也就是 a != a 是 true
}
Lambda表达式和函数指针,仿函数一样是可以调用对象,写法为[z](cons int x){return x>z;};
[]里面是捕获参数分为值捕获和引用捕获,可以在lambda表达式内部使用,()里面的是参数列表,{}里面是函数体,
返回类型,如果只有一条return语句的话,则可以通过return语句来判断返回类型,如果有其他的语句都默认返回void,如果要返回正确的类型,则需要用尾置返回类型,例如[z](cons int x)->bool{return x>z;};对于find_if,count_if等这些的可调用对象只支持一个参数的,用函数的指针不如用lambda表达式方便,lambda可以捕获一个值作为它的比较对象;
当需要在函数体内改变捕获的值则需要加mutable,例如[z]() mutable{return --z;};
Bind的绑定:auto newCallable=bind(callable,arg_list); newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对于callable的参数,它的参数有可能有占位符,如果有占位符需要用 using std::placeholders::_n , n为数字,例如
sort(iValue2.begin(), iValue2.end(),bind(Compare,_1,_2));
sort(iValue2.begin(), iValue2.end(),bind(Compare,_2,_1));
这两个是不同的排序,原因就是占位符,_1表示compare第一个参数,当前者sort调用A,B时,它会调用compare(A,B),而后者为compare(B,A);
当需要绑定引用参数的时候,需要用ref标准库函数,它的作用是返回一个对象,包含给定的引用,此对象可以拷贝,例如ostream对象的参数则需要用改函数。