天天看點

C++ lambda表達式入門1. 定義2. lambda表達式的使用

C++ lambda表達式入門

  • 1. 定義
  • 2. lambda表達式的使用
    • 2.1 最簡單的 lambda表達式
    • 2.2 加上參數清單
    • 2.3 再加點列印的東西
    • 2.4 傳回值
    • 2.5 捕捉變量
    • 2.6 STL應用

Reference:

  1. C++ lambda表達式入門

1. 定義

lambda 表達式 就是一個(匿名)函數,也就是一個沒有函數名的函數。為什麼不需要函數名呢,因為我們一次性的用它,嵌入式用的它,不需要在其他地方調用它。

lambda 表達式也叫閉包,閉就是封閉(其他地方都不調用)的意思,包就是函數。

lambda 表達式其實就是一個函數對象,他内部建立了一個重載()操作符的類。

lambda 表達式的簡單文法如下:[capture] (parameters) -> return value { body },隻有 [capture] 捕獲清單和 { body } 函數體是必選的,其他可選。

建立 lambda函數的一個原因是有些人希望建立一個能接受(lambda函數)參數的函數。

lambda 的引入給我們帶來了一種全新的程式設計體驗,它可以讓我們把 function 當做是 data 一樣傳遞,并且使我們從繁瑣的文法中解放出來,更加關注于“算法”本身。

新的

std::function

是傳遞 lambda函數的最好方式,不管是傳遞參數還是傳回值。

2. lambda表達式的使用

2.1 最簡單的 lambda表達式

int main()
{
	[] {}();//三部分,[] : 代表lambda表達式的開始;{} : 代表函數體,函數體裡面什麼都沒有;() : 代表函數調用.
}
           

等價于:

void f()
{
	
}
int main()
{
	f();
}
           

2.2 加上參數清單

像其他函數一樣,我們需要一個參數清單

()

,這樣

[] {}()

也可以寫為:

[](){}();

加了一個

()

代表函數參數,如果什麼參數都沒有,可以忽略

()

2.3 再加點列印的東西

int main()
{
	 [] { cout << "Hello, World!"<<endl; }();
}
           

也可以這樣:

int main()
{
	auto lam = [] { cout << "Hello, World!"<<endl; };
	lam();
}
           

2.4 傳回值

-> 代表此匿名函數傳回 int。大多數情況下 lambda表達式 的傳回值可由編譯器猜測得出,是以不需要特别指定傳回值類型。

int main()
{
	auto lam =[]() -> int { cout << "Hello, World!"; return 88; };
	//auto lam =[]() { cout << "Hello, World!"; return 88; };//自動推導傳回值
    auto ret = lam();
    cout<<ret<<endl;//輸出88
	auto lam2 =[]() -> string { cout << "Hello, World!"; return "test"; };
    auto ret1 = lam2();
    cout<<ret1<<endl;//輸出test
}
           

2.5 捕捉變量

變量捕捉才是成就 lambda表達式 卓越的秘方。

  • []

    : 不捕獲任何變量,這種情況下 lambda表達式 内部不能通路外部的變量;
  • [&]

    :以引用方式捕獲所有變量;
  • [=]

    :用值的方式捕獲所有變量 (可能被編譯器優化為 const &);
  • [=, &foo]

    :以引用方式捕獲變量

    foo

    ,但其餘變量都靠值捕獲;
  • [&,foo]

    :以值方式捕獲

    foo

    ,但其餘變量都靠引用捕獲;
  • [bar]

    :以值方式捕獲

    bar

    ,不捕獲其他變量;
  • [this]

    :捕獲所在類的

    this

    指針 (Qt 中使用很多,如此 lambda 可以通過 this 通路界面控件的資料)
int a=1,b=2,c=3;
auto lam2 = [&,a](){//b,c以引用捕獲,a以值捕獲。
	b=5;c=6;//a =1; a不能指派
	cout << a<<b<<c<<endl;//輸出 1 5 6
};
lam2();
           

2.6 STL應用

毋庸置疑,lambda 最大的一個優勢是在使用 STL 算法庫時:

vector<string> address{"111","222",",333",".org","wwwtest.org"};
for_each(address.begin(),address.end(),[](const string& str){cout<<str<<endl;});
// for_each為STL                       [](const string& str){cout<<str<<endl;}為lambda表達式
           

如此一行代碼就可以循環列印容器的資料。

再看一個例子,以前數組排序代碼是這樣的:

int arr[] = {6,4,3,2,1,5};
bool compare(int& a,int& b)//謂詞函數
{
    return a>b;
}
std::sort(arr, arr+6, compare);
           

用 lambda 表示:

std::sort(arr, arr+6, [](const int& a,const int& b){return a>b;});//降序排序
//std::sort(arr, arr+6, [](const auto& a,const auto& b){return a>b;}); //C++14支援基于類型推斷的泛型lambda表達式。
std::for_each(begin(arr),end(arr),[](const int& e){cout<<"After:"<<e<<endl;});//6,5,4,3,2,1
           

lambda表達式取代了謂詞函數,一行代碼搞定排序,再一行代碼搞定列印數組所有資料。