Lambda特性

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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章