在C ++中访问Lambda外部的Lambda Capture初始化变量

Eug*_*ene 4 c++ lambda initialization c++14

在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
}
Run Code Online (Sandbox Code Playgroud)

输出:

1个

2

value1变量访问之外的范围test()拉姆达?Lambda捕获初始化变量的生存期是多少?

尝试value1在lambda之外访问将给出以下信息error: ‘value1’ was not declared in this scope

与gcc版本7.3.0(Ubuntu 7.3.0-21ubuntu1〜14.04)一起编译。

Nic*_*las 5

Lambda只是用于内联定义的结构和该结构上的operator()重载(以及用于创建该结构类型的对象)的紧凑定义。Lambda“捕获”只是此结构的成员变量,由类型的构造函数初始化。这就是C ++ lambda必须具有按值或按引用捕获的语法的原因之一。

但是该结构的成员变量是私有的。而且由于编译器生成的结构很大程度上是实现定义的,因此标准不需要使用这些名称公开那些成员。如果需要,编译器生成的结构可以使用其他名称。编译器只需要重新映射这些名称的lambda用法即可引用成员的名称。

因此,不,任何类型的 Lambda捕获都无法被该Lambda之外的世界访问。如果捕获对对象的引用,则外界可能会访问该对象。但是您不会访问该对象的相同引用


rma*_*son 5

为了完整起见,根据编译器的不同,技术上可以访问 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;

}
Run Code Online (Sandbox Code Playgroud)

演示