簡體   English   中英

在 C++ 中訪問 lambda 之外的 lambda 捕獲初始化變量

[英]Accessing lambda capture initialized variable outside the lambda in C++

在 C++14/17 中,如何訪問 lambda 范圍之外的 lambda 捕獲初始化變量?

來源:

#include <iostream>

using namespace std;

int main(){
    auto test = [value1 =0]() mutable {value1+=1; return value1;};
    cout << test() << endl;
    cout << test() << endl;
    //cout << value1 << endl;//error: ‘value1’ was not declared in this scope
}

輸出:

1

2

value1變量是否可以在test() lambda 的范圍之外訪問? lambda 捕獲初始化變量的生命周期是多少?

嘗試在 lambda 之外訪問value1會出現以下error: 'value1' was not declared in this scope

使用 gcc 版本 7.3.0 (Ubuntu 7.3.0-21ubuntu1~14.04) 編譯。

lambda 只是內聯定義的結構和該結構上的operator()重載(以及用於創建該結構類型的對象operator()的緊湊定義。 Lambda“捕獲”只是這個結構的成員變量,由類型的構造函數初始化。 這是 C++ lambda 必須具有按值與按引用捕獲的語法的原因之一。

但是結構的成員變量是私有的。 並且由於編譯器生成的結構主要是實現定義的,因此標准不需要公開具有這些名稱的成員。 如果需要,編譯器生成的結構可以使用其他名稱; 編譯器只需要重新映射這些名稱的 in-lambda 用法即可引用成員的名稱。

所以不,任何形式的lambda 捕獲都不能被該 lambda 之外的世界訪問。 如果您捕獲對對象的引用,那么外部世界就有可能訪問同一個對象。 但是您不會訪問對該對象的相同引用

只是為了完整性,根據編譯器,技術上可以訪問 lambda 的內部成員並修改它們。 雖然這基本上是利用了一個實現細節,但永遠不應該這樣做。 但它確實提供了對 lambda 實現的一些見解。

這是在 GCC 6.3 中

#include <iostream>

using namespace std;

template<typename Lambda>
struct lambda_member : Lambda
{

    Lambda& f_;
    lambda_member(Lambda& f) : Lambda(f),
        f_(f)
    {}

    auto& get_value1()
    {
        return f_.__value1;
    }

};


int main(){
    auto test = [value1 =0]() mutable {value1+=1; return value1;};

    lambda_member<decltype(test)> lm{test};

    std::cout << test() << std::endl;
    std::cout << lm.get_value1() << std::endl;
    lm.get_value1() = 22;
    std::cout << test() << std::endl;

}

演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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