天天看點

C++閉包: Lambda Functions in C++11

C++閉包: Lambda Functions in C++11

表達式無疑是c++11最激動人心的特性之一!它會使你編寫的代碼變得更優雅、更快速! 它實作了c++11對于支援閉包的支援。首先我們先看一下什麼叫做閉包

維基百科上,對于閉包的解釋是:

in

programming languages, a closure (also lexical closure orfunction closure) is afunction

or reference to a function together with a referencing environment—a table storing areference to each

of the

non-local variables (also called

free variables or upvalues) of that function.[1] a closure—unlike

a plainfunction pointer—allows a function to access those non-local variables even when invoked outside its immediatelexical

scope.

the concept of closures was developed in the 1960s and was first fully implemented in 1975[citation

needed] as a language feature in the

scheme programming language to support lexically scoped

first-class functions. the use of closures is associated with

functional programming languages such as

lisp and

ml, as traditional imperative languages such as

algol,

c and

pascal do not support returning

nested functions as results from

higher-order functions and thus do not require supporting closures either. many moderngarbage-collected

imperative languages support closures, such as

smalltalk (the first object-oriented language to do so)[2],javascript

and

c#.

簡單來說,閉包(closure)是詞法閉包(lexical closure)或者函數閉包的簡稱,是引用了自由變量的函數。這個被引用的自由變量将和這個函數一同存在,即使已經離開了創造它的環境也不例外。是以,有另一種說法認為閉包是由函數和與其相關的引用環境組合而成的實體。

在程式設計語言中,變量可以分為自由變量(free variable)與限制變量(bound variable)兩種。簡單來說,一個函數裡局部變量和參數都被認為是限制變量;而不是限制變量的則是自由變量。

百度百科的解釋可能更加通俗易懂:

閉包是可以包含自由(未綁定到特定對象)變量的代碼塊;這些變量不是在這個代碼塊内或者任何全局上下文中定義的,而是在定義代碼塊的環境中定義(局部變量)。“閉包” 一詞來源于以下兩者的結合:要執行的代碼塊(由于自由變量被包含在代碼塊中,這些自由變量以及它們引用的對象沒有被釋放)和為自由變量提供綁定的計算環境(作用域)。在 scala、scheme、common lisp、smalltalk、groovy、javascript、ruby、

python和lua,objective c 等語言中都能找到對閉包不同程度的支援。

在程式設計領域我們可以通俗的說:子函數可以使用父函數中的局部變量,這種行為就叫做閉包!

還是上code吧:還是從hello, world!開始

我們可以像建立變量一樣友善的建立函數!使用stl我們會為了某個很簡單的實作不得不實作一個一個的小函數,

C++閉包: Lambda Functions in C++11

的引入可以讓我們寫出更緊湊的代碼:

僅僅通過sort和對于vector的周遊,我們就可以看到a lambda的巨大威力。當然了,對于c++11,我們可以使用“現代風格”進行數組的周遊:

另外一個快速示例:找到v裡面大于x并且小于y的第一個元素。在c++11中,最簡單和幹淨的代碼就是調用一個标準函數。

數組求和:

最後一個使得代碼高效優雅的例子:

下面對

C++閉包: Lambda Functions in C++11

表達式文法進行詳細的闡述:

C++閉包: Lambda Functions in C++11

1. lambda-introducer: 定義引用自由變量的方式。

    [] // 沒有定義任何變量。使用未定義變量會導緻錯誤。

    [x, &y] // x 以傳值方式傳入(預設),y 以引用方式傳入。

    [&] // 任何被使用到的外部變量皆隐式地以引用方式加以使用。

    [=] // 任何被使用到的外部變量皆隐式地以傳值方式加以使用。

    [&, x] // x 顯示地以傳值方式加以使用。其餘變量以引用方式加以使用。

    [=, &z] // z 顯示地以引用方式加以使用。其餘變量以傳值方式加以使用。

2. lambda-parameter-declaration-list: 參數清單。但是參數不可以有預設值,不可以使用變長參數,不可以有unamed arguments

3. mutable-specification :使得傳值引入的變量可以修改。這個修改因為是修改的外部變量的拷貝,是以并不會影響它本來的值

4. exception-specification:throw()該函數不能抛出異常。如果抛出異常,編譯器将報warning c4297。 throw(...) 可以抛出異常。throw(type)可以抛出type的異常

5. lambda-return-type-clause:如果僅有0/1個return的話可以省略。傳回值可以是lambda表達式。

最後一個問題, what's the type of a lambda expression? 使用c++11增強的各類function的wrapper std::function, 下面是使用

C++閉包: Lambda Functions in C++11

作為代理(delegate)的例子,僅僅是例子,不要問為什麼要這樣用:)

引用:

http://www.cprogramming.com/c++11/c++11-lambda-closures.html

http://rednaxelafx.iteye.com/blog/184199

http://www.cplusplus.com/reference/algorithm/sort/

lambda expression syntax

http://msdn.microsoft.com/en-us/library/46h7chx6.aspx

http://msdn.microsoft.com/en-us/library/dd293599.aspx#higherorder