Доступ к лямбда-захвату инициализированной переменной вне лямбды в C ++ - PullRequest
0 голосов
/ 21 октября 2018

В C ++ 14/17, как получить доступ к инициализированной переменной лямбда-захвата вне области действия лямбды?

Источник:

#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() лямбда?Каково время жизни инициализированной лямбда-переменной захвата?

Попытка доступа к value1 вне лямбды дает следующее error: ‘value1’ was not declared in this scope.

Скомпилировано с gcc версии 7.3.0 (Ubuntu 7.3.0-21ubuntu1 ~ 14.04).

Ответы [ 2 ]

0 голосов
/ 21 октября 2018

Просто для полноты, в зависимости от компилятора, технически можно получить доступ к внутренним элементам лямбды и изменить их.Хотя это в основном использует детали реализации, и никогда не должно быть сделано.Но он дает некоторое представление о лямбда-реализации.

Здесь это в 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;

}

Демо

0 голосов
/ 21 октября 2018

Лямбда - это просто компактное определение для встроенной структуры и перегрузки operator() для этой структуры (и для создания объекта типа этой структуры).Лямбда-захваты - это просто переменные-члены этой структуры, инициализированные конструктором типа.Это одна из причин, почему лямбда-выражения C ++ должны иметь синтаксис для захвата по значению по сравнению со ссылкой.

Но переменные-члены структуры являются закрытыми.А поскольку структура, сгенерированная компилятором, в значительной степени определяется реализацией, стандарт не требует предоставления этих членов с этими именами.Генерируемая компилятором структура может использовать другое имя, если оно того хочет;компилятору просто нужно переназначить использование этих имен в лямбда-выражениях для ссылки на имена членов.

Так что нет, лямбда-захваты любого вида не могут быть доступны миру за пределамиэта лямбда.Если вы фиксируете ссылку на объект, то внешний мир может получить доступ к тому же объекту.Но вы не получите доступ к той же ссылке на этот объект.

...