Разница между захватом и передачей аргумента в лямбда-функциях

Я понимаю лямбда-функцию и ее цель в С++ 11. Но я не понимаю разницы между "Захват значения" и "Передача аргумента". Для экземпляра..

#include <iostream>
#include <functional>
using namespace std;

int add(int a,int b){
    return a+b;
}

int main(int argc, char** argv){

    function <int(int,int)> cppstyle;
    cppstyle = add;

    auto l = [] (function <int(int,int)> f,int a, int b) {return f(a,b);};

    cout << l(cppstyle,10,30) <<"\n";   
}

Вывод кода выше того же кода, что и код ниже.

#include <iostream>
#include <functional>
using namespace std;

int add(int a,int b){
    return a+b;
}

int main(int argc, char** argv){

    function <int(int,int)> cppstyle;
    cppstyle = add;

    auto l = [cppstyle] (int a, int b) {return cppstyle(a,b);};

    cout << l(10,30) <<"\n";    
}

Захват значения аналогичен передаче значения в качестве аргумента? или захват имеет какое-то особое значение?

Ответы

Ответ 1

Различие между захваченным аргументом и передающим аргументом можно увидеть с аналогией. Рассмотрим следующий объект функции:

struct Capture {
  int &i;
  int const j;
public:
  Capture(int &_i, int &_j) : i(_i), j(_j) {}
  int operator()(int const a, int const b) {
    i *= j;
    return a * b;
  }
};

В классе объектных объектов Capture существуют две переменные-члены i и j. Там также перегружен operator(), который принимает два входных аргумента. Теперь рассмотрим следующую лямбду:

int i, j;
[&i, j](int const a, int const b) {
  i *= j;
  return a * b;
};

Переменные-члены класса Capture аналогичны лямбда-захвату (т.е. [&i, j]), тогда как входные аргументы перегруженных operator() a и b аналогичны входным аргументам a и b представленной выше лямбда.

То есть, если вы рассматриваете лямбду как объект функции, ее захват является состоянием объекта функции (т.е. его переменными-членами), тогда как его входные аргументы будут входными аргументами перегруженного operator().

Ответ 2

На более высоком уровне вы фиксируете данные, которые знаете сейчас, и передаете данные, которые у вас есть, пока вам не понадобится выполнить вызов.

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

void Add(std::vector<int>& v, int i)
{
    std::for_each(std::begin(v), std::end(v), [i](int& j){ j += i; });
}