2011-08-27 59 views
7

例如:規則拉姆達捕獲變量

class Example 
{ 
public: 
    explicit Example(int n) : num(n) {} 
    void addAndPrint(vector<int>& v) const 
    { 
     for_each(v.begin(), v.end(), [num](int n) { cout << num + n << " "; }); 
    } 
private: 
    int num; 
}; 

int main() 
{ 
    vector<int> v = { 0, 1, 2, 3, 4 }; 

    Example ex(1); 
    ex.addAndPrint(v); 
    return 0; 
} 

當你編譯和運行MSVC2010這您會收到以下錯誤:

錯誤C3480: '例子:: NUM':一個lambda捕獲變量必須是從一個封閉函數作用域

然而,隨着克++ 4.6.2(預發佈)你得到:

根據標準草案哪個編譯器是正確的?

+3

請注意,您必須在這裏按值來捕獲'this',而不是'num'。當你使用'num'時,你真的使用'this-> num'。另請注意,MSVC沒有實現lambda表達式的C++ 11措辭,因爲它在2008年後實現了這一切。 –

+0

@Alexandre:捕獲'this'與通過引用捕獲'num'實際上是一樣的。這似乎不是這裏所期望的。 –

+0

// @本:很好。然而結果在這裏是一樣的,因爲閉包不會轉義addAndPrint的作用域(而且整個事情很可能在這裏被內聯)。 5.1.2由@dimitri引用似乎表明MSVC是正確的,因爲'num'不是具有自動存儲持續時間的變量。然而,這種行爲很奇怪。 –

回答

7

5.1.2/9:

The reaching scope of a local lambda expression is the set of enclosing scopes up to and including the innermost enclosing function and its parameters.

和5.1.2/10:

The identifiers in a capture-list are looked up using the usual rules for unqualified name lookup (3.4.1); each such lookup shall find a variable with automatic storage duration declared in the reaching scope of the local lambda expression.

作爲num既不以任何功能範圍中聲明也不具有自動存儲的持續時間,它不能被捕獲。因此VS是正確的,而g ++是錯誤的。

+0

感謝您的澄清。我發現g ++ 4.6.2有一些關於捕獲的bug,例如'[=,this]'也在編譯,他們打算修復它們爲4.7.0。 –

0

標準說以下(5.1.2):

在捕獲列表的標識符擡起頭來使用不合格的名稱查找(3.4.1)的一般規則;每個 這樣的查找應該找到一個在本地 lambda表達式的範圍內聲明的具有自動存儲持續時間的變量。

根據我的理解,GCC編譯器是正確的,因爲'num'處於lambda聲明點的範圍內。

+2

僅在範圍內是不夠的,它必須是具有自動存儲時間的變量**。 –