簡體   English   中英

為什么我們需要捕獲lambda中引用的引用?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM