歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C++拾遺--lambda表達式

前言

    有時,我們需要在函數內部頻繁地使用某一功能。此時,我們可以把這種功能寫成一個獨立的函數。而實際上,這個新的函數很可能是不需要在其它的地方進行調用的。我們想限定它的作用范圍,最好是僅限於當前函數。而函數的內部是不可以重新定義其它的函數的。為了解決這個問題,在新的標准中,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