程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> c++11 新特性之lambda表達式,lambda表達式

c++11 新特性之lambda表達式,lambda表達式

編輯:C++入門知識

c++11 新特性之lambda表達式,lambda表達式


  寫過c#之後,覺得c#裡的lambda表達式和delegate配合使用,這樣的機制用起來非常爽。c++11也有了lambda表達式,形式上有細小的差異。形式如下:

  c#:(input parameters) => {statement;}

  c++:[capture list](parameter list) -> return type {statement;}

  c++lambda表達式共分為4各部分。其中parameter list 和 return type 是可以在特定情況下省略的。

一、capture list

  capture list的作用是捕獲lambda所在函數的局部變量。其中捕獲的類型可以分為值捕獲,引用捕獲和隱式捕獲。

  值捕獲:

1 void fun()
2 {
3     int a = 1; 
4     auto f = [a] { return a; };
5     a = 0;
6     auto r = f(); 
7     cout << r << endl;
8 }

  結果是1。 和函數值傳遞一樣,行4 lambda表達式捕獲的v1是fun函數中局部變量a的一份拷貝,因此行5改變了a並不影響 lambda表達式內的a。

  引用捕獲:

1 void fun()
2 {
3     int a = 1;
4     auto f = [&a] { return a; };
5     a = 0;
6     auto r = f(); 
7     cout << r << endl;
8 }

  結果為0,行4 捕獲的是a對象本身。但是值得一提的是采用引用捕獲要保證lambda表達式工作時,引用的變量還是要存在的。

  隱式捕獲:

  隱式捕獲的方式,就是capture的列表可以用'='和'&'代替,讓編譯器隱式的推斷你使用的是那個變量,然後這兩個字符表示捕獲的類型‘=’表示值捕獲,'&'是引用捕獲。采用隱式捕獲的方式上述兩段代碼的行4可以分別表示為:

  auto f = [=] {return a;}

  auto f = [&] {return a;}

  如果需要,你也可以選擇混合使用這幾種方式:

  

 1 void fun()
 2 {
 3     int a = 1;
 4     int b = 2;
 5     int c = 3;
 6     auto f = [&,a]{cout << "a = " << a << " b=" << b << " c="  << c;};
 7     a++;
 8     b++;
 9     c++;
10     f();
11 }

 

 

  輸出結果 : a = 1 b=3 c=4

  不難發現 b,c都是采用的引用捕獲的方式而a采用的值捕獲的方式。隱式捕獲是這樣工作的:對於['=' or '&',capture list or null ]這樣捕獲列表 ,parameter 是非必須的,相當於對前一種情況的特化(例如template特化那樣)。即,如果前一個位置采用了‘=’,capture list可以選擇那些需要引用捕獲的局部變量或者為空(但是不可以也是值捕獲的局部變量)。‘&’同理。

二、parameter list

  大體來說parameter list用法和普通的函數類似。c++11標准規定lambda表達式不可以有默認參數,但是我在g++ 4.8 和vs2013分別測試如下代碼,g++能通過並且給出期望的結果,vs2013報錯說lambda表達式不可以有默認參數。顯然g++對c++11進行了擴展,為了代碼的可移植性,我們還是應該嚴格遵守標准。

  具體參考c++11文檔:5.1.2.5 節:

  The closure type for a lambda-expression has a public inline function call operator (13.5.4) whose param- eters and return type are described by the lambda-expression’s parameter-declaration-clause and trailing- return-type respectively. This function call operator is declared const (9.3.1) if and only if the lambda- expression’s parameter-declaration-clause is not followed by mutable. It is neither virtual nor declared volatile. Default arguments (8.3.6) shall not be specified in the parameter-declaration-clause of a lambda- declarator. Anyexception-specificationspecifiedonalambda-expressionappliestothecorrespondingfunction call operator. An attribute-specifier-seq in a lambda-declarator appertains to the type of the corresponding function call operator. 

 

1 int fun()
2 {
3     auto f = [](string s1,string s2){cout << s1 << s2;};
4     f("hello ","world\n");
5     auto f2 = [](string s1,string s2="hahah\n"){cout << s1 << s2;};
6     f2("eric ");
7 }

 

 

 

三、return type

 

  lambda- declarator 中 返回類型也必須是c++11的尾置返回類型(trailing return type)。並且可以省略,可以交給編譯器去推斷。(vs2013和g++在lambda體使用了if時皆可以推斷出返回類型,當然每個if-else分支返回的類型應該統一,否則需要加上位置返回類型的聲明)。

 

四、mutable

  在lambda表達式的parameter list 和 return type之間加上關鍵詞 mutable ,表示 捕獲的值可以在{}中改變,而默認情況捕獲的值是不允許改變的(但是捕獲的引用是可以改變的)。或許是為了效率,不加mutable的之前的值捕獲,可以少開辟一些內存,只有加上mutable之後才真正的為捕獲的值分配內存。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved