0

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; }
1
  • You could read the documentation topic on lambda expressions. It lists the different capture modes, and unlike what you're reading, doesn't contain comments like or, a scorched earth strategy?. What does that even mean in this context? Commented Aug 8, 2016 at 18:05

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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

Comments

2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.