2013-10-30 37 views
22

如果引用類型的變量是按值在lambda中捕獲的,它是否被引用或值捕獲?在lambda中,如何通過值捕獲引用

小樣本有問題:

#include <iostream> 

struct Test { 
    int a; 
}; 

void testFunc(const Test &test) { 
    auto a = [=] { 
    // does 'test' is being passed to closure object with copy 
    // or by reference? 
    return test.a; 
    }(); 
    std::cout << a; 
} 

int main() { 
    Test test{1}; 
    testFunc(test); 
} 
+2

那麼,測試它呢? (您需要修改該對象,可以通過嘗試使用非const引用或通過使變量爲'mutable'來實現。) –

+0

看起來是[value](http://ideone.com/R0HclW )。 –

+0

@JanHudec是的,測試是好的,但看到相關標準的章節和理論基礎的答案(SO上有許多這樣的專家)總是有用的。 – Yury

回答

19

按價值。編譯例子:

class C 
{ 
public: 
    C() 
    { 
     i = 0; 
    } 

    C(const C & source) 
    { 
     std::cout << "Copy ctor called\n"; 
     i = source.i; 
    } 

    int i; 
}; 

void test(C & c) 
{ 
    c.i = 20; 

    auto lambda = [=]() mutable { 

     c.i = 55; 
    }; 
    lambda(); 

    std::cout << c.i << "\n"; 
} 

int main(int argc, char * argv[]) 
{ 
    C c; 
    test(c); 

    getchar(); 
} 

結果:

Copy ctor called 
20

我想,那C++標準的適用本款:

5.1.2 Lambda表達式

(...) 14.如果一個實體被隱式捕獲,則捕獲實體 拷貝,並且 捕獲默認值 = =或者如果明確地 捕獲與不包含&的捕獲。對於通過複製捕獲的每個實體,在封閉類型中聲明一個未命名的非靜態數據成員。這些成員的聲明順序是未指定的。 如果實體不是對對象的引用 或引用類型的引用,則此類數據成員的類型是相應捕獲實體的類型。 [ 注意:如果捕獲的實體是對函數的引用,則對應的數據成員也是對函數的引用。 - end note]

這實際上是有道理的 - 如果局部變量通過值傳遞,參數通過引用傳遞「行爲」作爲函數中的局部變量,爲什麼會通過引用而不是值傳遞?

+2

索賠的任何引用(如規範中的章節和段落號)? –

+5

我認爲重要的原因是通過價值捕獲是存在的,所以只要閉包是變量就是有效的。如果引用沒有被剝離,那麼這將不起作用。 –

相關問題