2011-03-29 35 views
11

在最近的C++ 0x草案(n3225.pdf)之一,我們可以發現5.1.2/10:瞭解的C++ 0x的λ捕獲

在捕獲列表的標識符擡頭使用通用規則進行非限定名稱查找(3.4.1);每個這樣的查找應該在本地lambda表達式的範圍內找到一個具有自動存儲持續時間的變量。如果一個實體(即一個變量或這個)出現在lambda表達式的捕獲列表中,則被認爲是顯式捕獲的。

似乎相當嚴格的給我。例如,它似乎我下面的事情是不允許的:

int global; 

struct s { 
    int x; 
    void memfun() { 
     [x,global]{}; 
    } 
}; 

因爲x不一定與自動存儲一個變量,也不是global。請注意,此捕獲條款的目的是讓lambda對象存儲副本xglobal,這些副本在稍後階段進行更改時可能需要。我已經知道一種替代的:

int global; 

struct s { 
    int x; 
    void memfun() { 
     int copyx = x; 
     int copyglobal = global; 
     [copyx,copyglobal]{}; 
    } 
}; 

但這歸結爲額外的拷貝和額外的鍋爐板只是捕捉xglobal的副本。

而且,我無法找到任何東西一下如果我們將其命名捕獲子句中的本地引用會發生什麼最新的草案結論:

int main() { 
    int i = 0; 
    int &r = i; 
    assert([r]{return &r;}() != &i); 
} 

是否拉姆達對象「複製一個參考」或「複製一個int 「?如果它通過複製捕獲被引用的對象,這可以爲我們節省以前解決方法的額外副本。

GCC顯然支持所有這些例子,並在最後一種情況下存儲一個int的副本(這是可取的,恕我直言)。但是我想知道這是否實際上是根據C++ 0x草案的預期行爲,還是僅僅是一個編譯器擴展,實際上是一個實現錯誤。

編輯:

templatetypedef指出5.1.2/14這也說明當參考在捕獲子句被命名爲會發生什麼。據我所知,這讓我們可以使用下面的變通的第一個例子:

int global; 

struct s { 
    int x; 
    void memfun() { 
     auto& cx = x; 
     auto& cglob = global; 
     [cx,cglob]{}; 
    } 
}; 

蒂亞, sellibitze

+0

注意:C++ 14擴展了可能的捕獲子句集合 – sellibitze 2014-07-01 14:13:44

回答

11

從看來你已經發布什麼樣的你的第一個例子是因爲這兩個捕獲變量都沒有自動持續時間,所以是非法的 但是,您可以輕鬆解決此問題。要捕獲數據成員,您可以捕獲此數據,並且不需要捕獲全局數據,因爲您可以直接引用它。

編輯:正如您所指出的,這不會創建您想要捕獲的值的本地副本。 要在創建副本時捕獲這些變量,可以捕獲這些變量,然後在lambda內部顯式創建數據成員的本地副本。

至於關於捕獲參考的第二個問題,§ 5.1.2/14表示通過拷貝捕獲參考類型的變量將創建引用的值的副本,而不是創建參考的副本。因此,lambda將擁有自己創建時引用所引用的值的副本。

+1

捕獲子句中命名'x'和'global'的意思是讓lambda對象存儲* copy *。如果':: global'和's :: x'改變它們的值,這可能是可取的。所以,不,捕捉「這個」並不會導致預期的行爲。 – sellibitze 2011-03-29 09:17:24

+0

你是對的;我剛剛更新了我的答案。感謝您指出了這一點! – templatetypedef 2011-03-29 09:27:01

+2

感謝您指出5.1.2/14。看起來,如果我們有興趣通過複製捕獲其他東西,我們可以引入對非自動變量的本地引用作爲解決方法。 – sellibitze 2011-03-29 09:38:21