I'm building a lambda function that requires access to a fair number of variables in the context.
const double defaultAmount = [&]{
/*ToDo*/
}();
I'd rather not use [=]
in the list as I don't want lots of value copies to be made.
I'm concerned about program stability if I use [&]
since I don't want the lambda to modify the capture set.
Can I pass by const reference? [const &]
doesn't work.
Perhaps a good compiler optimises out value copies, so [=]
is preferable.
By default, variables are captured by const value . This means when the lambda is created, the lambda captures a constant copy of the outer scope variable, which means that the lambda is not allowed to modify them.
The mutable keyword is used so that the body of the lambda expression can modify its copies of the external variables x and y , which the lambda expression captures by value. Because the lambda expression captures the original variables x and y by value, their values remain 1 after the lambda executes.
The lambda is capturing an outside variable. A lambda is a syntax for creating a class. Capturing a variable means that variable is passed to the constructor for that class. A lambda can specify whether it's passed by reference or by value.
The [=] you're referring to is part of the capture list for the lambda expression. This tells C++ that the code inside the lambda expression is initialized so that the lambda gets a copy of all the local variables it uses when it's created.
You can create and capture const references explicitly:
int x = 42;
const int& rx = x;
auto l = [&rx]() {
x = 5; // error: 'x' is not captured
rx = 5; // error: assignment of read-only reference 'rx'
};
The capture list is limited in what can be captured; basically by-value or by-reference (named or by default), the this
pointer and nothing.
From the cppreference;
capture-list - a comma-separated list of zero or more captures, optionally beginning with a capture-default. Capture list can be passed as follows (see below for the detailed description):
[a,&b]
wherea
is captured by value andb
is captured by reference.[this]
captures thethis
pointer by value[&]
captures all automatic variables odr-used in the body of the lambda by reference[=]
captures all automatic variables odr-used in the body of the lambda by value[]
captures nothing
You could create local const&
to all the object you wish to capture and use those in the lambda.
#include <iostream>
using namespace std;
int main()
{
int a = 5;
const int& refa = a;
const int b = [&]() -> int {
//refa = 10; // attempts to modify this fail
return refa;
}();
cout << a << " " << b << endl;
}
The capture could be either for all the references, or an explicit list what is required;
const int b = [&refa]()
Another alternative is not to capture the local variables at all. You then create a lambda that accepts as arguments the variables you need. It may be more effort as the local variable count grows, but you have more control over how the lambda accepts its arguments and is able to use the data.
auto lambda = [](const int& refa /*, ...*/) { */...*/ }
lambda(...);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With