Difference between capture and passing an argument in lambda functions
The difference between a captured argument and a passing argument could be seen with an analogy. Consider the following function object:
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;
}
};
In function object class Capture
there are two member variables i
and j
. There's also overloaded operator()
which takes two input arguments. Now consider the following lambda:
int i, j;
[&i, j](int const a, int const b) {
i *= j;
return a * b;
};
The member variables of class Capture
are in analogy with the lambda capture (i.e., [&i, j]
), whereas input arguments of overloaded operator()
a
and b
are in analogy with input arguments a
and b
of the lambda shown above.
That is, if you consider a lambda as a function object, its capture is the state of the function object (i.e., its member variables) whereas its input arguments would be the input arguments of the overloaded operator()
.
At a higher level, you capture the data you know now, and you pass in the data you don't have until you need to make the call.
For instance, let's say you wanted to add a constant to every number in a vector. Your could write it like (caution: untested):
void Add(std::vector<int>& v, int i)
{
std::for_each(std::begin(v), std::end(v), [i](int& j){ j += i; });
}
The capture of i value is set when the lambda was defined, while when i is passed as argument (j), it is changing in the loop.
#include <iostream>
using namespace std;
int main(int argc,char **argv) {
auto i=5;
auto f = [=](int j) {cout<<"capture i="<<i<<", passing i as j="<<j<< endl; };
while (i<30) {
i += 10;
f(i);
}
}
--- This will be the output:
lambda capture i=5, passing i as argument j=15
lambda capture i=5, passing i as argument j=25
lambda capture i=5, passing i as argument j=35