Difference between capture and passing an argument in lambda functions

10,435

Solution 1

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().

Solution 2

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; });
}

Solution 3

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

Share:
10,435
01000001
Author by

01000001

Updated on June 10, 2022

Comments

  • 01000001
    01000001 about 2 years

    I understand the lambda function and the purpose of it in c++ 11. But i do not understand the difference between "Capturing the value" and "Passing an argument". For Instance..

    #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";   
    }
    

    The output of the code above is same as the code below..

    #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";    
    }
    

    Is "capturing a value" similar to "passing a value as an argument"? or capture has some special meaning?