2013-05-01 44 views
49

我明白捕捉this在拉姆達(修改對象屬性)的正確方法如下:爲什麼我不能在lambda中捕獲這個通過引用('&this')?

auto f = [this]() { /* ... */ }; 

不過我很好奇,下面的特點我見過:

class C { 
    public: 
     void foo() { 
      // auto f = []() { // this not captured 
      auto f = [&]() { // why does this work? 
      // auto f = [&this]() { // Expected ',' before 'this' 
      // auto f = [this]() { // works as expected 
       x = 5; 
      }; 
      f(); 
     } 

    private: 
     int x; 
}; 

,我迷茫了(並想回答)的古怪就是爲什麼以下工作:

auto f = [&]() { /* ... */ }; // capture everything by reference 

爲什麼我不能明確上尉URE this參考:

auto f = [&this]() { /* ... */ }; // a compiler error as seen above. 
+3

你爲什麼想要?對於指針的引用可能會被認爲有用的事物而言:「this」不能被改變,它不足以使得引用更快......並且**無論如何**,_it doesn'實際上是存在的,所以它沒有真正的生命週期,這意味着任何對它的引用都會被定義爲懸而未決的。 '這是一個價值,而不是一個左值。 – 2016-08-16 15:38:34

回答

64

原因[&this]不能正常工作,是因爲它是一個語法錯誤。在lambda-introducer每個逗號分隔的參數是capture

capture: 
    identifier 
    & identifier 
    this 

你可以看到,&this是不允許的語法。不允許的原因是因爲你永遠不想通過引用捕獲this,因爲它是一個小的const指針。你只會想要通過價值來傳遞它 - 所以這種語言不支持通過引用捕獲this

要明確捕獲this,您可以使用[this]作爲lambda-introducer

第一capture可以是capture-default它是:

capture-default: 
    & 
    = 

這意味着分別捕獲自動任何我使用,通過引用(&)或值(=) - 然而的this所述治療是特別 - 在這兩種情況下,由於先前給出的原因(即使默認捕獲&,通常意味着通過引用捕獲),它被捕獲。

5.1.2.7/8:

對於名稱查找(3.4)的目的,在確定的類型和this值(9.3.2)和轉化ID- 表達式參照非靜態類成員使用(*this)(9.3.1), 將組合語句[OF THE LAMBDA]考慮在lambda表達式的上下文中。

所以拉姆達行爲,如果它(在你的例子一樣使用名稱x的)使用成員名稱時是包圍部件功能的一部分,所以它會產生就像一個的this「隱習慣」成員函數呢。

如果λ-捕獲包括捕獲默認即&,在λ-捕獲標識符不得 前面加&。如果拉姆達捕獲包括捕獲默認值=,則拉姆達捕獲不應包含 this並且其包含的每個標識符之前應有&。在lambda捕獲中,標識符或this不應出現超過 。

所以,你可以使用[this][&][=][&,this]作爲lambda-introducer按值來捕捉this指針。

然而[&this][=, this]是不合格的。在最後一種情況下,gcc原諒地爲[=,this]發出explicit by-copy capture of ‘this’ redundant with by-copy capture default而非錯誤的警告。

+0

我想知道,是否有任何理由*不*使用'[&]'或'[=]'?爲什麼我想要明確指定標識符,如果編譯器完全能夠自己搞清楚要捕獲什麼? – 2013-05-01 18:11:17

+3

@KonradRudolph:如果你想通過引用來捕獲一些價值和其他東西,那麼該怎麼辦?或者想要明確你捕獲的內容? – Xeo 2013-05-01 18:12:43

+1

@KonradRudolph:這是一個安全功能。您可能會無意中捕捉到您不想要的名稱。 – 2013-05-01 18:12:57

0

由於標準不具有捕獲&this列出:

N4713 8.4.5.2捕獲:

lambda-capture: 
    capture-default 
    capture-list 
    capture-default, capture-list 

capture-default: 
    & 
    = 
capture-list: 
    capture...opt 
    capture-list, capture...opt 
capture: 
    simple-capture 
    init-capture 
simple-capture: 
    identifier 
    &identifier 
    this 
    * this 
init-capture: 
    identifier initializer 
    &identifier initializer 
  • 對於的目的lambda捕獲,表達式可能引用本地實體,如下所示:

    7.3此表達式潛能lly引用* this。

  • 所以,標準保證this*this是有效的,並且&this是無效的。此外,捕獲this裝置捕獲*this(這是一個左值,對象本身)通過引用而非由值捕獲this指針

    +0

    這不會添加任何不在其他答案 – 2017-12-07 19:22:41

    +0

    @AnthonySottile最後一段旨在糾正您的答案。 – czxyl 2017-12-09 00:14:54

    +0

    有人可以告訴我原因嗎? – czxyl 2017-12-09 02:46:38

    相關問題