谓词
含义
指可调用的表达式,作为算法的一个实参传进去。标准库算法用的谓词只有一元谓词(接受一个参数)和二元谓词
实例
通过定义一个可调用函数,作为参数传入sort函数。
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <algorithm>
#include <typeinfo>
using namespace std;
bool isShorter(const string &s1, const string &s2) //二元谓词
{
return s1.size()<s2.size();
}
int main() {
vector<string> vec ={"01","0"};
sort(vec.begin(), vec.end(), isShorter);
for(auto &ele: vec)
cout<<ele<<endl;
return 0;
}
lambda
动机
算法函数支持谓词固定,比如find_if函数只接受一元谓词,但你写的谓词是接受好多参数,这样就用不了。
bool isShorter1(const string &s1, const int &sz)
{
return s1.size()>= sz;
}
//找到长度大于sz的字符串
find_if(vec.begin(), vec.end(), isShorter1); //xxx。不支持二元谓词
可调用对象
函数、函数指针、重载了调用运算符的类、lambda表达式。
定义形式
[capture list](param list)->return type { fuction body; } // (param list)->return type可没有
返回类型可省略,这样人家就推断类型(不要相信,很可能错误类型)
捕获只用于局部非static变量
1、捕获列表是捕获lambda表达式所在函数内的局部非static变量,就是捕获普通局部变量,局部静态想用就用。
2、捕获列表为空可以使用当前函数之外的任何在当前函数作用域里的变量
用法
把多的参数设为捕获。
find_if(vec.begin(), vec.end(), [sz](const string &a){ return a.size()>=sz}); //形参只有一个a了
lambda的捕获和返回
lambda定义的本质
lambda可看作同时定义一个类类型和创建一个对象。对象是匿名的。
值捕获是创建lambda时拷贝
捕获列表的值捕获是创建时拷贝,参数列表是调用时拷贝。
void fcn()
{
int j = 42;
auto f = [j]{return j};
j = 0;
auto m = f(); //还是输出42
}
引用捕获不拷贝 ,是创建lambda时绑定
void fcn()
{
int j = 42;
auto f = [&j]{return j};
j = 0;
auto m = f(); //输出0
}
最后返回引用时要保证引用的对象存在
隐式捕获
可以使用[&]或[=],即直接隐式捕获,挺方便的。
find_if(vec.begin(), vec.end(), [=](const string &a){ return a.size()>=sz}); //sz不用显式捕获了了
推断的类型不靠谱
transform(vi.begin(). vi.end(), vi.begin(), [](int i) {if(i<0) return -i; else return i;}); //xxx。很不幸推断成void了
//改成
transform(vi.begin(). vi.end(), vi.begin(), [](int i)->int {if(i<0) return -i; else return i;});