謂詞
含義
指可調用的表達式,作爲算法的一個實參傳進去。標準庫算法用的謂詞只有一元謂詞(接受一個參數)和二元謂詞
實例
通過定義一個可調用函數,作爲參數傳入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;});