C++ lambda表達式
lambda表達式組成
[捕獲列表](參數列表)->返回類型{函數體}
- 參數列表和返回類型可以省略,但捕獲列表和函數體必須包含;
- 捕獲列表通常爲空,返回類型必須使用尾置返回;
- 例:
auto f = []{return 42;};
捕獲列表
- 只用於局部非static變量
- 值捕獲:捕獲的變量值是在lambda表達式創建時變量的拷貝,而不是調用時的拷貝
void fcn1(){
int v1=42;
auto f=[v1]{return v1;};
v1=0;
auto j=f(); //j=42
}
- 引用捕獲:捕獲的是變量的引用,而不是拷貝。
void fcn2(){
int v1=42;
auto f=[&v1]{return v1;};
v1=0;
auto j=f(); //j=0
}
隱式捕獲
- 使得編譯器自己推斷捕獲列表,我們可以告訴編譯器使用值捕獲還是引用捕獲:
[=]
採用值捕獲;[&]
採用引用捕獲;
顯式捕獲隱式捕獲混用
- 捕獲列表的第一個元素必須是
=
或者&
; - 顯式捕獲必須使用和隱式捕獲不同的方式:
[=, var]
:var必須爲引用捕獲[&,var]
:var必須爲值捕獲
可變lambda
- 在值捕獲的lambda表達式中,如果想要改變該變量的值,必須加上關鍵字mutable:
void fcn3(){
int v1=42;
auto f=[v1]() mutable {return ++v1;};
v1=0;
auto j=f();//j=43
}
- 在引用捕獲中,能否改變捕獲變量的值取決於該變量是否是const:
void fcn4(){
int v1=42;
auto f=[&v1](){return ++v1;};
v1=0;
auto j=f();//j=1
}
捕獲列表的作用:
當可調用對象只能接受一個參數,但是需要兩個或者多個參數才能完成操作時,這個時候lambda表達式的參數列表只能有一個,哪另外一個參數怎麼傳進來呢?就是靠捕獲列表;
如果要使用函數來替代lambda表達式的功能,碰到這種只能傳入單一參數的情況,還有一種解決方式,使用標準庫bind函數。
bind函數 (functional頭文件)
- 先定義一個可以傳入兩個或多個參數完成操作的函數
bool func1(int a1,int a2){
return a1>=a2;
}
- 然後使用bind函數將這個func1函數再封裝一層:
auto func2=bind(func1,_1,6);
- 其中
_1
_2
…是佔位符,代表func2的第一個、第二個…參數,我們這裏我們將func1的第二個參數綁定爲6,這樣,func2就變成了一個只需要傳入一個參數的函數(可調用對象);func2傳入的參數類型和返回類型和func1完全一樣。 - 使用佔位符需要使用std::placeholders命名空間:
using namespace std::placeholders;
使用bind可以重排參數順序
- 函數g只需要傳入兩個參數,
g(m,n)
,則m
和n
會分別傳入_1
和_2
的位置:
auto g=bind(f,a,b,_2,c,_1);
即g(m,n)
等價於f(a,b,n,c,m)