歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> C++拾遺--lambda表達式

C++拾遺--lambda表達式

日期:2017/3/1 9:32:55   编辑:Linux編程

前言

有時,我們需要在函數內部頻繁地使用某一功能。此時,我們可以把這種功能寫成一個獨立的函數。而實際上,這個新的函數很可能是不需要在其它的地方進行調用的。我們想限定它的作用范圍,最好是僅限於當前函數。而函數的內部是不可以重新定義其它的函數的。為了解決這個問題,在新的標准中,C++引入了lambda表達式(lambda expression)的概念。有了lambda表達式,C++向一門完美的語言又進了一大步。總的來說,lambda表達式極大地提升了C++的函數運用能力。

lambda表達式
《C++Primer》中對它的描述是“一個lambda表達式表示一個可調用的代碼單元,可理解為一個未命名的內聯函數”。lambda表達式的一般形式是

[capture list] (parameter list) ->return type {function body}


capture list -> 捕獲列表(必選)
parameter list -> 參數列表(可選)
function body -> 函數主體(必選)
return type -> 返回值類型(可選)

下面我們一一探討

感性認識

#include <iostream>
#include <string>
using namespace std;
int main()
{
//定義一個lambda表達式
auto print = [](string s){
for (int i = 0; i < s.size(); i++)
cout << s[i] << " ";
cout << endl;
};

string man = "man";
string woman = "woman";
string say = "ILOVEYOUBABY";

//對print的調用形同一個函數
print(man);
print(woman);
print(say);

cin.get();
return 0;
}

運行

capture list(捕獲列表)
在捕獲列表中指明需要用到的局部變量(全局變量可直接使用,不需捕獲)。兩種捕獲方式:值捕獲、引用捕獲。

需要指出:捕獲列表只用於捕獲局部非static變量。

1.值捕獲

前提:被捕獲的變量是可以被拷貝的。
重點:在值捕獲時,默認情況下,是不可以修改捕獲列表中變量的值的,除非在parameter list後加關鍵字mutable。
難點:拷貝的時機是在lambda表達式定義時,而不是使用時。
實例

#include <iostream>
using namespace std;

int g_data(1);

int main()
{
//data的定義必須在lambda表達式之前,否則無法捕獲
int data(2);
auto fun = [data]()mutable{
//在lambda表達式中,修正data的值
data = 3; //若不加mutable,此處會error
g_data = 4;
};
cout << "fun()調用之前" << endl;
cout << "g_data = " << g_data << ends << "data = " << data << endl;
//修正data的值
data = 5;
//在修正後進行調用,以驗證值捕獲的時機
fun();
cout << "fun()調用之後" << endl;
cout << "g_data = " << g_data << ends << "data = " << data << endl;
cin.get();
return 0;
}

運行

2.引用捕獲
在變量名前加&,即為引用捕獲。它和引用的語法一樣。
實例

#include <iostream>
using namespace std;

int main()
{
cout << "引用捕獲演示" << endl;
int data(0);
cout << "fun()調用之前 ";
cout << "data = " << data << endl;
auto fun = [&data](){
data++; //由於是引用捕獲,在修改值時,mutable可以不加
};
//調用fun()
fun();
cout << "fun()調用之後 ";
cout << "data = " << data << endl;
cin.get();
return 0;
}

運行

隱式捕獲
隱式捕獲並不是第三種捕獲方式,它只是捕獲列表的一種書寫方式。
幾種常見的寫法
[&] 所有變量均采用引用捕獲。
[=] 所有變量均采用值捕獲。
[&,identifier_list] identifier_list是一個用逗號隔開的參數列表,這個列表中的局部變量使用值捕獲,其它的使用引用捕獲。
[=,identifier_list] identifier_list是一個用逗號隔開的參數列表,這個列表中的局部變量使用引用捕獲,且變量名前需添加&,其它的使用值捕獲。
特別的,空捕獲列表[]:表示lambda表達式中不能使用任何局部變量。

實例

#include <iostream>
using namespace std;

int main()
{
int a, b, c;
a = b = c = 0;
//在fun1中a、b、c都采用值捕獲
auto fun1 = [=]()mutable{
a++;
b++;
c++;
};
//在fun2中a、b、c都采用引用捕獲
auto fun2 = [&](){
a++;
b++;
c++;
};
//在fun3中a采用引用捕獲,b、c采用值捕獲
auto fun3 = [=, &a](){
a++;
};
//在fun4中b、c采用引用捕獲,a采用值捕獲
auto fun4 = [&, a](){
b++;
c++;
};
fun1();
cout << "fun1() a = " << a << " b = " << b << " c = " << c << endl;
a = b = c = 0;
fun2();
cout << "fun2() a = " << a << " b = " << b << " c = " << c << endl;
a = b = c = 0;
fun3();
cout << "fun3() a = " << a << " b = " << b << " c = " << c << endl;
a = b = c = 0;
fun4();
cout << "fun4() a = " << a << " b = " << b << " c = " << c << endl;
cin.get();
return 0;
}

運行

parameter list(參數列表)
參數列表和普通函數的參數列表用法基本一致,除了一點:不可以有默認實參。
即是不可以有這種寫法:[](int a=0){};


function body和return type
三點規則:
若function body中只有一條return語句,則return type可以沒有,返回值類型由return語句推測。
若無return語句,則返回值類型為void.
若除了return語句外還有其它語句,則必須指定返回值的類型,且必須使用尾置返回類型,即"->類型名"的形式。

------------------------------分割線------------------------------

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm

讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm

將C語言梳理一下,分布在以下10個章節中:

  1. Linux-C成長之路(一):Linux下C編程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成長之路(二):基本數據類型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成長之路(三):基本IO函數操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成長之路(四):運算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成長之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成長之路(六):函數要義 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成長之路(七):數組與指針 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成長之路(八):存儲類,動態內存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成長之路(九):復合數據類型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成長之路(十):其他高級議題

Copyright © Linux教程網 All Rights Reserved