Using [&]

I have recently come across some code that looks a little like this:

auto name = [&](unsigned long long bla, unsigned long long bla2)
{
return bla + bla2;
};

What exactly does this code do? Specifically, the part "[&]()" as I have never come across this before.
It's a lambda function. Basically a local function. In your example.. name would be a function pointer which points to the lambda. You would then call that function like so:

 
auto x = name(5,6);  // x=11 


The brackets [] indicate it's a lambda. The '&' inside the brackets indicates it inherits the scope of the function its contained in:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
    int localvar = 0;

    auto foo = [&] ()
    {
        localvar = 5;  // OK, foo inherits the scope of main
    }

    auto bar = [] ()
    {
        localvar = 3;  // ERROR, localvar is not in this scope.
    }
}
The term you need to google to find out more about [&], etc is "lambda capture".

[&] means capture by reference (by default)
[=] means capture by value (by default)
[] means capture nothing

And you can also specify specific variables in the capture clause.

[&, foo] and [foo, &] mean capture foo by value but everything else by reference
[=, &bar] and [&bar, =] mean capture bar by reference but everything else by value
[&foo, bar] and [bar, &foo] mean capture just foo (by reference) and bar (by value)

But be aware that when you capture a variable it's not always the same one as found in the enclosing scope. Here the lambda "bar" gets a copy of the variable.

[main] : value = 0, addr = 0x23ff5c

[foo ] : value = 5, addr = 0x23ff5c

[main] : value = 5, addr = 0x23ff5c

[bar ] : value = 8, addr = 0x23ff54

[main] : value = 5, addr = 0x23ff5c


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
using namespace std;

int main() {
    int localvar = 0;

    cout << "[main] : value = " << localvar  << ", "
         << "addr = " << &localvar << "\n\n";

    auto foo = [&] ()
    {
        localvar = 5;

        cout << "[foo ] : value = " << localvar  << ", "
             << "addr = " << &localvar << "\n\n";
    };

    auto bar = [=] () mutable // lambda must be mutable if you want
    {                         // to set a variable captured by value
        localvar = 8;

        cout << "[bar ] : value = " << localvar  << ", "
             << "addr = " << &localvar << "\n\n";
    };

    foo();

    cout << "[main] : value = " << localvar  << ", "
         << "addr = " << &localvar << "\n\n";

    bar();

    cout << "[main] : value = " << localvar  << ", "
         << "addr = " << &localvar << "\n\n";

    return 0;
}


Andy

Lambda Expression Syntax
https://msdn.microsoft.com/en-us/library/dd293603.aspx
Last edited on
Thanks for your replies, I think I understand now.

One last question, what would be the benefits of using a lambda function over a regular function? Any examples would be greatly appreciated.
Locality. (It keeps code that does stuff in one spot.)

For example, you can flip the case in a string:

1
2
3
4
std::transform( std::begin(s), std::end(s), []( char c ) -> char 
{ 
  return std::isupper( c ) ? std::tolower( c ) : std::toupper( c ); 
} );

Whereas before, you would have to reference a function that does that:

 
std::transform( std::begin(s), std::end(s), some_func_somewhere_else );

That last one is a maintenance headache.

Hope this helps.
Topic archived. No new replies allowed.