Является ли Lambda Expression просто захватом объектов перед этим? [Дубликат]

Помимо добавления соединителя JDBC MySQL убедитесь, что context.xml (если он не распакован в папке webapps Tomcat) с вашими определениями соединений с БД включены в каталог Tomcats conf.

6
задан Evan Harper 24 October 2011 в 20:51
поделиться

4 ответа

С помощью лямбда-выражения привязанные переменные захватываются во время объявления .

Этот пример будет очень ясен: https: // ideone. com / Ly38P

 std::function<int()> dowork()
 {
      int answer = 42;
      auto lambda = [answer] () { return answer; };

      // can do what we want
      answer = 666;
      return lambda;
 }

 int main()
 {
      auto ll = dowork();
      return ll(); // 42
 }

Ясно, что захват должен происходить перед вызовом, так как захватываемые переменные даже не существуют (не в масштаб, ни в жизни) больше в более позднее время.

13
ответ дан sehe 19 August 2018 в 17:48
поделиться
  • 1
    Я думаю, вы откровенно упрощены здесь. Лямбда-объект существует и в стеке, и в содержании его захвата. Он копируется в объект function в точке возврата, используя конструктор копирования шаблона function, который управляет тиканием стирания стилей и выделяет вызываемую копию в куче. – v.oddou 20 June 2016 в 10:16

Он связан во время создания. Рассмотрим:

#include <functional>
#include <iostream>

std::function<int(int)> foo;

void sub()
{
    int a = 42;
    foo = [a](int x) -> int { return x + a; };
}

int main()
{
    sub();
    int abc = 54;
    abc = foo(abc); // Note a no longer exists here... but it was captured by
                    // value, so the caller shouldn't have to care here...
    std::cout << abc; //96
}

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

6
ответ дан Billy ONeal 19 August 2018 в 17:48
поделиться

Да, у него есть для захвата по значению в точке, потому что иначе вы могли бы попытаться захватить переменную (например, по ссылке), которая больше не существует, когда функция лямбда / функция действительно вызывается.

Стандарт поддерживает захват как по значению И по ссылке, так и для обоих возможных вариантов использования. Если вы скажете компилятору зафиксировать по значению, он будет захвачен в точке создания лямбда. Если вы попросите захватить по ссылке, он будет захватывать ссылку на переменную, которая затем будет использоваться в точке, на которой вызывается лямбда (требуя, конечно, чтобы ссылочная переменная все еще существовала в точке вызов выполнен).

-1
ответ дан Mark B 19 August 2018 в 17:48
поделиться

Я думаю, вы путаете механизм захвата с механизмом передачи переменной. Они не то же самое, даже если они несут какое-то поверхностное сходство друг с другом. Если вам нужно текущее значение переменной внутри лямбда-выражения, запишите его по ссылке (хотя, конечно, эта ссылка привязана к определенной переменной в точке, объявленной лямбдой).

Когда вы «захватить» переменную, вы создаете нечто вроде закрытия. А замыкания всегда статичны (т. Е. «Захват» происходит в точке объявления). Люди, знакомые с понятием лямбда-выражения, найдут лямбда-выражения C ++ очень странными и запутанными, если бы это было иначе. Добавление совершенно новой функции на язык программирования, отличный от той же функции на других языках программирования, каким-то значительным образом сделало бы C ++ еще более запутанным и трудным для понимания, чем это уже есть. Кроме того, все остальное на C ++ статически ограничено, поэтому добавление некоторого элемента динамического охвата будет очень странным по этой причине.

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

3
ответ дан Omnifarious 19 August 2018 в 17:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: