C ++ лямбда-значение не может захватить

0

Вот мой код, я хочу проверить закрытие в c++, как javascript. Почему компилятор передает это сообщение? "testLambda.cpp: В лямбда-функции: testLambda.cpp: 8: 11: ошибка: 'а не зафиксировано"

    #include <iostream>
    #include <functional>
    std::function<bool(int)> returnLambda(int a){
        auto b  = 1;
        auto c  = 2;

        return [&](int x)
        {   return x*(b++)+c+a == 0;};
    }
    auto f = returnLambda(21);
    int main(){
        auto c = f(1);
        auto b = f(1);

        std::cout<<c<<b<<std::endl;
        return 0;
    }
  • 3
    [] где вы помещаете переменные захвата.
  • 1
    Если у вас есть проблема, которая решается с помощью ответа, но затем вы сталкиваетесь с новой проблемой, не меняйте свой вопрос. Задайте новый вопрос, в другом посте.
Показать ещё 2 комментария
Теги:
lambda

2 ответа

6
Лучший ответ

Вам нужно указать свои захваты в квадратных скобках, поэтому лямбдам требуется, в первую очередь, квадратные скобки. Вы можете захватить их по ссылке:

[&a,&b,&c] (int x) ...

или по значению:

[a,b,c] (int x) ...

или смешать его:

[a,&b,c] (int x) ...

Или вы можете просто захватить все, что вы используете:

[&] (int x) ... // by reference
[=] (int x) ... // by value

Если вы решите захватить переменную по значению, но вам нужно ее изменить, вам необходимо сделать ее изменчивой:

[=] (int x) mutable ...
  • 0
    Спасибо, я немного изменяю свой код, но он говорит об ошибке сегментации. Проблема в том, что в лямбда-функции есть «а»
  • 1
    @Ryan_Liu - Если вы захватываете по ссылке, вы несете ответственность за обеспечение того, чтобы объект был еще жив, когда вызывается лямбда
Показать ещё 1 комментарий
1

Бенджамин Линдли дал ответ об объявлении лямбда в C++.

Но технически говоря, вы не можете воспроизвести закрытие JavaScript, используя C++ lambdas.

В JS внешние переменные, используемые локальной функцией, защищены механизмом GC.

Но в C++, если вы фиксируете переменные по ссылке, вы можете легко попасть в ситуацию, когда ссылочные переменные будут уничтожены, и вы получите нарушение сегментации/нарушение прав доступа.

Это, например:

#include <iostream>
#include <functional>
std::function<bool(int)> returnLambda(int a){
    auto b  = 1;
    auto c  = 2;

    return [&](int x)
    {   return x*(b++)+c == 0;};
}
auto f = returnLambda(21);
int main(){
    auto c = f(1);
    auto b = f(1);

    std::cout<<c<<b<<std::endl;
    return 0;
}

будет сильно повреждаться, поскольку после возврата из returnLambda() его переменные a, b и c уничтожаются (их расположение стека используется чем-то другим) при вызове функции f().

  • 0
    Если вам нужно такое поведение, сделайте ваши локальные переменные общими указателями и перехватите их по значению в лямбда-выражении.
  • 0
    @ Бенджамин Линдли Да, в C ++ есть техника для симуляции замыканий, но это действительно симуляция. Закрытие в JS - это ссылка на функцию + ссылка на цепочку кадров вызова (объекты в куче). Таким образом, в основном вся техника должна моделировать эту цепочку вызовов в той или иной форме.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню