Isabella Lu
Isabella Lu

Reputation: 11

Lambda function capture a variable vs return value?

I am learning c++11 new function lambda function and am a little confused. I read that

 []         Capture nothing (or, a scorched earth strategy?)
 [&]        Capture any referenced variable by reference
 [=]        Capture any referenced variable by making a copy
 [=, &foo]  Capture any referenced variable by making a copy, but capture variable foo by reference
 [bar]      Capture bar by making a copy; don't copy anything else
 [this]     Capture the this pointer of the enclosing class

My question is what exactly does capture a variable mean and what's the difference with return a value, if you want to capture a variable you have to return it right?

For example:

[] () { int a = 2; return a; } 

Why is it not

int [] () { int a = 2; return a; }

Upvotes: 0

Views: 3388

Answers (3)

kfsone
kfsone

Reputation: 24249

One of the key features of a lambda function is that it can remember things from the scope in which it was declared:

#include <iostream>
#include <vector>
#include <functional>

auto f(int i, int j) {
    int k = i * j;
    return [=](){ std::cout << k << "\n"; };
}

int main() {
    std::vector<std::function<void(void)>> v;
    v.push_back(f(2,2));
    v.push_back(f(6, 7));
    for (auto& l: v) {
        l();
    }
}

Note how we don't have to pass anything to the lambda when we call it?

Lambdas are essentially syntactic sugar around functor objects, and capture is the process of adding member variables to the functor:

[](char* p){ *p = toupper(*p); }

struct Lambda1 {
    int operator(char* p) const { *p = toupper(*p); }
};

int x = 42;
int y = 5;
[x, &y](int i){ return i * (x + y); }

struct Lambda2 {
    int x_;
    int& y_;
    Lambda2(int x, int& y) : x_(x), y_(y) {}
    int operator(int i) { return i*(x_ + y_); }
};

Returning a value from a lambda is optional, but the return value is the output of the lambda, not the input.

Upvotes: 2

KABoissonneault
KABoissonneault

Reputation: 2369

The capture list is for bringing symbols into the lambda. A return value is for, well, returning a value out of a lambda.

Also, lambdas use the trailing return type syntax, like this [] () -> int { int a=2; return a; }. Though often it's better to leave it implicitely deduced

Upvotes: 2

aschepler
aschepler

Reputation: 72271

You can "capture" variables that belong to the enclosing function.

void f() {
    int a=1;
    // This lambda is constructed with a copy of a, at value 1.
    auto l1 = [a] { return a; };
    // This lambda contains a reference to a, so its a is the same as f's.
    auto l2 = [&a] { return a; };

    a = 2;

    std::cout << l1() << "\n"; // prints 1
    std::cout << l2() << "\n"; // prints 2
}

You can return a captured variable if you want, or you can return something else. The return value is unrelated to captures.

Upvotes: 4

Related Questions