[英]why do we need to capture reference for a reference in lambda?
考慮一下:
class TestLambda {
public:
std::vector<char> data;
};
void test_lambda(TestLambda& obj) {
[=]() mutable {
obj.data.push_back(0x01);
}();
}
int main() {
TestLambda tst;
tst.data.push_back(0x99);
test_lambda(tst);
// tst.data is unchanged at this point
return 0;
}
在調用test_lambda
,我期望看到tst.data
的更改,但事實並非如此。 要查看更改,我必須創建lambda再次傳遞obj
的引用,即。 [&obj]()
。
我們為什么需要這個? 我的意思是,再一次參考?
obj
已經是一個參考。 然后, lambda
通過復制來捕獲obj
。 那么, lambda
本身內的obj
不是引用? 為什么?
有人能解釋一下嗎? 謝謝。
當在分配的右側使用時,引用就像“正常”變量一樣。 每當你通過值定義lambda捕獲時,lambda擁有外部變量的副本,就像lambda以這些行開頭一樣:
auto my_inner_variable = my_outer_reference;
auto my_inner_other_variable = my_outer_other_variable;
如果您希望引用“保留”引用,則必須通過引用捕獲它,從而指示編譯器發出如下代碼:
auto& my_inner_variable = my_outer_reference;
auto& my_inner_other_variable = my_outer_other_variable; // if we instructed to capture everything by reference
根據標准草案§5.1.2/ p15 Lambda表達式[expr.prim.lambda] ( Emphasis Mine ):
如果隱式捕獲實體,並且capture-default為=,或者如果使用不是形式&identifier或&identifier初始化程序的捕獲顯式捕獲實體,則通過副本捕獲實體。 對於由副本捕獲的每個實體,在閉包類型中聲明未命名的非靜態數據成員。 這些成員的聲明順序未指定。 如果實體不是對對象的引用,則這種數據成員的類型是對應的捕獲實體的類型,否則是引用的類型。 [注意:如果捕獲的實體是對函數的引用,則相應的數據成員也是對函數的引用。 - 結束注釋]匿名工會的成員不得通過副本獲取。
因此,在:
void test_lambda(TestLambda& obj) {
[=]() mutable {
obj.data.push_back(0x01);
}();
}
obj
是通過復制捕獲的,因此您可以正確地獲得所描述的結果。 換句話說,這是標准規定[=]
捕獲默認值的行為。
您的函數test_lambda
包含嵌套的lambda函數。 在test_lambda
,引用obj
指的是main中的tst
。 然后你調用一個按值捕獲的匿名lambda函數。 在lambda函數內部, obj
是test_lambda中的obj
的副本。 為什么不簡單寫:
void test_lambda(TestLambda& obj) {
obj.data.push_back(0x01);
}
您現在正在做的事情也許可以說明一下
void test_lambda(TestLambda& obj) {
[=]() mutable {
objCopy.data.push_back(0x01);
}();
}
其中objCopy
是由捕獲lambda的值創建的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.