lambda是c++11的一個非常好的新特性,當需要添加一個臨時的函數時,使用lambda非常方便。
lambda的寫法如下:
[函數外部對象參數](函數參數) -> 返回值類型{ 函數體 }
1.[ ]中的函數外部對象參數,允許在函數體內直接調用函數外部的參數。
2.( )中的函數參數,同正常函數的參數一樣,是每次函數調用傳入的變量。
3.->後面跟着的是函數的返回值類型。
4. {}中可以編寫邏輯,並使用[]和()中傳入的參數。
定義在lambda函數相同作用域的參數引用也可以被使用,這種參數集合一般被稱爲閉包,[ ]中可以填寫下面幾種類型的參數,將定義lambda函數的作用域內的變量傳入函數體中。
1.[ ]沒用任何參數,這種情況下不傳入外部參數。
2.[a, &b]傳入變量a的值以及變量b的引用。
3.[&]以引用方式傳入所有變量。
4.[=]以傳值的方式傳入所有變量,但值不可被修改。
5.[&, a]除了a以值的方式傳入,其餘的所有變量以引用方式傳入。
6.[=, &a]除了a以引用的方式傳入,其餘的所有變量以值的方式傳入。
下面編寫一個測試用例,當在lambda函數中使用了=傳入的參數,且對引用參數或外部參數進行賦值操作後,會產生意想不到的結果,而在使用&時需要注意的是引用對象的生命週期。
#include <iostream>
void main()
{
int a, b, c;
auto fun0 = [&]()->void{ a = 1; b = 2; c = 3; };
auto fun1 = []()->int {return 2 * 3; };
auto fun2 = [=, &a, &b]()->void {++a, b += c + a; };
auto fun3 = [=]()->int {return a + c; };
fun0();
std::cout << a << "\t" << b << "\t" << c << std::endl;
c = fun1();
std::cout << a << "\t" << b << "\t" << c << std::endl;
fun2();
std::cout << a << "\t" << b << "\t" << c << std::endl;
b = fun3();
std::cout << a << "\t" << b << "\t" << c << std::endl;
}
運行結果如下:因爲默認情況下,Lambda函數總是一個const函數,用mutable可以取消其常量性。按照規定,一個const的成員函數是不能在函數體內修改非靜態成員變量的值。所以有=傳入時不要對傳入的參數進行賦值操作。
當lambda被定義在類的成員函數中時,lambda可以調用該類的private函數;當lambda調用該類的成員函數時,操作成員變量或其他成員函數時,需要將this傳入,=和&會傳入this。
使用std::function可以存儲lambda函數。例如,可以用function<void()>來存放fun(),function<int()>來存放fun1,帶參數的函數可以在()內輸入參數類型,在使用function時要包含頭文件functional。
#include <functional>
std::function<void()> f1 = fun0;
std::function<int()> f2 = fun1;
function還可以用於存放普通函數,靜態函數和類的共有成員函數,前兩者和lambda的用法一樣,直接將函數名賦值給function對象即可(無法識別重載的函數),但類的成員函數需要使用bind來綁定。classA *obj = new classA;
std::function<void(int)> f3 = std::bind(&classA::memberFun1, obj, std::placeholders::_1);
std::function<void(int, char)> f4 = std::bind(&classA::memberFun2, obj, std::placeholders::_1, std::placeholders::_2);
delete obj;
使用bind綁定成員函數和對象指針,使用placeholders佔位符來表示函數的參數數量,依次爲1~N。