天天看點

Lambda 表達式文法Lambda 表達式文法

本主題介紹 lambda 表達式的文法。 它示範提供 lambda 表達式的結構元素的示例,這些元素與示例。

下面用于定義顯示文法,ISO C++11 從标準,lambda 表達式 (項标記下标 選擇 是可選的):

         lambda-introducer lambda-declarator 選擇 compound-statement

進一步失敗的元件這些文法如下:

lambda-introducer: 

         [ lambda-capture 選擇 ] 

lambda-capture:

        capture-default

        capture-list

         capture-default , capture-list 

capture-default:

        &

        =

capture-list:

         capture ... 選擇 

         capture-list , capture ... opt 

capture:

        identifier

         & identifier 

        this

lambda-declarator:

         ( parameter-declaration-clause ) mutable 選擇 

                 exception-specification 選擇 attribute-specifier-seq 選擇 trailing-return-type 選擇 

Visual Studio 支援 C++11 标準 Lambda 表達式文法及其所有 C++11 功能與除了 lambda,以下操作:

可選的 attribute-specifier-seq 不支援。

Visual Studio 向 C++11 lambda 功能通過添加以下功能:

無狀态是 lambda omni 轉換的任意函數使用調用約定的函數的指針。

比 { return expression; } 複雜的主體的 lambda 自動傳回這樣的類型,隻要所有傳回語句具有相同的類型。(這在 C++14 标準現在建議的)。

下圖将該文法映射到示例。

Lambda 表達式文法Lambda 表達式文法

圖中的标注如下所示:

lambda-introducer(在本主題的後面稱為“capture 子句”)

lambda declarator(在本主題的後面稱為“參數清單”)

mutable(在本主題的後面稱為“可變規範”)

exception-specification(在本主題的後面稱為“異正常範”)

trailing-return-type(在本主題的後面稱為“傳回類型”)

compound-statement(在本主題的後面稱為“lambda 體”)

以下各節對該文法進行了更詳細的說明。

lambda 表達式是類、構造和函數調用運算符。 如同,在定義類時,決定需要發生的對象捕獲變量不受值還是引用或者是否是必需的。 如果 lambda 表達式需要通路局部變量和函數參數,它們需要 捕獲。 get 子句 (文法中的lambda-introducer ) 所指定 lambda 表達式的主體是可以通路在封閉範圍内的變量通過值或通過引用:包含" &的變量 (&) 為字首) 沒有 & 字首的引用和變量通路值由通路。

空 capture 子句 [ ] 訓示 lambda 表達式的主體不通路封閉範圍中的變量。

捕獲預設模式指定您未顯式指定的擷取變量是否捕獲通過值或通過引用,如果使用它們。 您可以通過将 & 或 = 指定為 capture 子句的第一個元素來指定預設捕獲模式(文法中的 capture-default)。 & 元素指定 lambda 表達式的主體通過引用通路所有捕獲的變量,除非您顯式地另行指定。 = 元素指定 lambda 表達式的主體通過值通路所有捕獲的變量,除非您顯式地另行指定。 例如,如果 lambda 表達式的主體通過引用通路外部變量 total 并通過值通路外部變量 factor,那麼以下 capture 子句等效:

有關使用 capture-default 的一種常見的誤會位于範圍内的任何變量捕獲是否使用 lambda。 事實上并非如此 - 在 lambda 提到的那些變量捕獲,則使用 capture-default。

如果捕獲子句包括 capture-default&,該 lambda 的 get 子句 capture 的 identifier 不能由 &。 沿着同一行,是以,如果擷取子句包括 capture-default (=),該子句獲得每個 capture 必須以窗體 & identifier。 辨別符或 this 不能多次出現在子句獲得。 下面的代碼段闡釋了一些示例。

在使用子句獲得時,應記住這些,了解和壓力,尤其當使用具有多線程時的 lambda:

引用擷取可用于修改變量之外,擷取值,而無法用于修改變量之外 (變量允許複制修改,從原始的)。

而值擷取不會反映更新給變量,則擷取引用會反映更新到變量中。

而值擷取沒有生存期依賴關系,這些依賴關系的引用,擷取引入生存期依賴關系,這些依賴關系。

許多這些點在這和相關文章中的代碼示例所示。

參數清單 (lambda declarator) lambda 表達式中為選項并類似于函數的參數清單。

lambda 表達式的參數清單可以是可選的。 可以省略空括号,如果不傳遞參數到 lambda 表達式,并且 lambda-declarator: 不包含 exception-specification、trailing-return-type、mutable。

通常的 lambda 函數調用運算符為 Const 按值,但是,mutable 可以取消此操作。 它不導緻變量的資料成員。 可變規範使用 lambda 表達式的主體修改由捕獲值的變量。 某些示例本文後面示範了 mutable 關鍵字的用法。

如果 lambda 體包含單個傳回語句或 lambda 表達式不傳回值,則可以省略 lambda 表達式的傳回類型部分。 如果 lambda 體包含單個傳回語句,編譯器将從傳回表達式的類型推導傳回類型。 否則,編譯器會将傳回類型推導為 void(可能需要顯示指明傳回類型)。 考慮闡釋此原則下面的示例代碼段。

lambda 表達式主體的 lambda (compound-statement) 中可以包含一般的方法或函數主體所能包含的所有内容。 普通函數和 lambda 表達式的主體均可通路以下變量類型:

參數

本地聲明變量

類資料成員 (在聲明類和 this 内捕獲)

具有靜态存儲持續時間的任何變量(例如,全局變量)

此外,lambda 表達式可以通路它從封閉範圍中捕獲的變量。 如果某個變量顯示在 lambda 表達式的 capture 子句中,則該變量是顯式捕獲的。 否則,該變量是隐式捕獲的。 lambda 表達式的主體使用預設捕獲模式來通路隐式捕獲的變量。

以下示例包含通過值顯式捕獲變量 n 并通過引用隐式捕獲變量 m 的 lambda 表達式:

本示例将以下内容輸出到控制台:

由于變量 n 是通過值捕獲的,是以在調用 lambda 表達式後,變量的值仍保持 0 不變。 指定 mutable 允許 n 是在 lambda 中修改。

盡管 lambda 表達式隻能捕獲具有自動存儲持續時間的變量,但您可以在 lambda 表達式的主體中使用具有靜态存儲持續時間的變量。 以下示例使用 generate 函數和 lambda 表達式為 vector 對象中的每個元素指派。 lambda 表達式将修改靜态變量以生成下一個元素的值。

下面的代碼示例使用從前面的函數,并将該表達式的 lambda 表達式的示例與 STL generate_n的算法。 該 lambda 表達式配置設定的 vector 對象的元素。前兩個元素的和的。 改用 mutable 關鍵字,這樣 lambda 表達式體才能改變其外部變量 x 和 y的複制,lambda 表達式按值捕獲。 由于 lambda 表達式按值捕獲原始變量 x 和 y,它們的值保持為 1,在 lambda 後執行。

繼續閱讀