Can a lambda capturing nothing access global variables?
Yes, sure. Normal name lookup rules apply.
[expr.prim.lambda]/7 ... for purposes of name lookup ... the compound-statement is considered in the context of the lambda-expression.
Re: why local variables are treated differently from global ones.
[expr.prim.lambda]/13 ... If a lambda-expression or an instantiation of the function call operator template of a generic lambda odr-uses (3.2)
this
or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression.[expr.prim.lambda]/9 A lambda-expression whose smallest enclosing scope is a block scope (3.3.3) is a local lambda expression... The reaching scope of a local lambda expression is the set of enclosing scopes up to and including the innermost enclosing function and its parameters.
In your example, m
is a variable with automatic storage duration from the lambda's reaching scope, and so shall be captured. n
is not, and so doesn't have to be.
How can I access of a variable inside a lambda without using a global variable?
Use lambda with capture. Notice the [&]
.
Here is a demo.
#include <iostream>
using namespace std;
int main() {
int k=0;int n=0;
auto func1=[=]()mutable{k=1;n=1;}; //capture k by value
func1();
std::cout<<k<<std::endl; //print 0
auto func2=[&](){k=2;n=1;}; //capture k by reference
func2();
std::cout<<k<<std::endl; //print 2 (k changed)
auto func3=[k]()mutable{k=3;/* n=1; compile fail*/}; //capture k by value
func3();
std::cout<<k<<std::endl; //print 2
auto func4=[&k](){k=4; /* n=1; compile fail*/}; //capture k by reference
func4();
std::cout<<k<<std::endl; //print 4 (k changed)
}
More about mutable
: Why does C++0x's lambda require "mutable" keyword for capture-by-value, by default?
GCC incorrectly captures global variables by reference in lambda functions?
§5.1.2/11:
If a *lambda-expression( has an associated capture-default and its compound-statement odr-uses (3.2)
this
or a variable with automatic storage duration and the odr-used entity is not explicitly captured, then the odr-used entity is said to be implicitly captured; ...
Global variables have static storage duration (§3.7.1), so the global a
will not be implicitly captured by value. Still, you can access a global variable anywhere, so
[=]() { a = 9; } ();
will set the global a
to 9 as expected.
Explicitly capturing a global should be an error or UB, because §5.1.2/10 says
The identifiers in a capture-list are looked up using the usual rules for unqualified name lookup (3.4.1); each such lookup shall find a variable with automatic storage duration declared in the reaching scope of the local lambda expression.
using out of scope variables in C++11 lambda expressions
You need to capture the variable, either by value (using the [=]
syntax)
bool repeated = std::any_of(agents.begin(), agents.end(),
[=](P_EndPoint i)->bool
{return requestPacket.identity().id()==i.id();});
or by reference (using the [&]
syntax)
bool repeated = std::any_of(agents.begin(), agents.end(),
[&](P_EndPoint i)->bool
{return requestPacket.identity().id()==i.id();});
Note that as @aschepler points out, global variables with static storage duration are not captured, only function-level variables:
#include <iostream>
auto const global = 0;
int main()
{
auto const local = 0;
auto lam1 = [](){ return global; }; // global is always seen
auto lam2 = [&](){ return local; }; // need to capture local
std::cout << lam1() << "\n";
std::cout << lam2() << "\n";
}
lambda function accessing outside variable
You can "capture" the i
when creating the lambda
lambda x, i=i: x%i==0
This will set the i
in the lambda's context equal to whatever i
was when it was created. you could also say lambda x, n=i: x%n==0
if you wanted. It's not exactly capture, but it gets you what you need.
It's an issue of lookup that's analogous to the following with defined functions:
glob = "original"
def print_glob():
print(glob) # prints "changed" when called below
def print_param(param=glob): # default set at function creation, not call
print(param) # prints "original" when called below
glob = "changed"
print_glob()
print_param()
Why is my global, extern lambda variable not initialized at runtime?
The problem had to do with static initialization order. Since the lambdas often relied on each other already being initialized in a specific order, the initialization would not happen and the global lambdas would be left in an invalid state, thus causing the std::bad_function_call
exceptions at runtime.
To fix the problem, I moved the initialization of the global lambda variables to runtime.
How can I disable implicit lamba variable capture?
The only "implicit capture" happens with the static and global variables in the scope. And there's no way to get rid of this.
Why capture lambda does not working in c++?
auto kitten = [=] () {return g+1;}
This lambda doesn't capture anything at all. It's nearly the same as just
int kitten() { return g+1; }
Only local variables can be captured, and there are no local variables visible in the scope of the kitten
definition. Note that [=]
or [&]
don't mean "capture everything", they mean "capture anything necessary", and a global variable is never necessary (or possible) to capture in a lambda, since the meaning of that variable name is always the same no matter when the lambda body is evaluated.
auto cat = [g=g] () {return g+1;}
Here's an init-capture, which is similar to creating a local variable and immediately capturing it. The g
before the equal sign declares the init-capture, and the g
after the equal sign specifies how to initialize it. Unlike most declarators (see below), the g
variable created here is not in scope in its own initializer, so the g
after the equal sign means the global variable ::g
. So the code is similar to:
auto make_cat()
{
int & g = ::g;
return [g]() { return g+1; }
}
auto cat = make_cat();
auto kitten = [] () {int g = g; return g+1;}
This code has a mistake not really related to lambdas. In the local variable definition int g = g;
, the declared variable before the equal sign is in scope during the initializer after the equal sign. So g
is initialized with its own indeterminate value. Adding one to that indeterminate value is undefined behavior, so the result is not predictable.
How can I access a non-final variable in a Thread lambda?
Suppose this was allowed? What would you expect it to return?
// Warning! This is an example of what *NOT* to do.
//
public Response get(String endpoint) {
Response response = new Response();
new Thread(() -> {
response = OffredUtil.makeGetRequest(endpoint);
}).start();
return response;
}
There's no reason to think that response = OffredUtil.makeGetRequest(endpoint);
statement will be executed until before the return response;
statement. In fact, it probably will not be executed until some time later.
What you really want is;
- for your
get(endpoint)
method to return a mutable object, and - a way for a caller to wait until a new value has been stored into the mutable object by some other thread.
The Java standard library defines an interface for just that kind of mutable object: It's called java.util.concurrent.Future
. A Future
has a get()
method that will wait, if necessary, until some other thread has completed the Future by giving it a value, and then the get()
will return the value.
The simplest way to use it is through the CompletableFuture
class:
import java.util.concurrent.Future;
import java.util.concurrent.CompletableFuture;
...
public Future<Response> get(String endpoint) {
return CompletableFuture.supplyAsync(() -> {
return OffredUtil.makeGetRequest(endpoint);
});
}
A call to this get(endpoint)
method will submit a task to a built-in thread pool that will execute the given lambda expression, and then it will return a Future
that will be completed by the task.
If the lambda produces a value, then that will become the value of the Future
. If the lambda throws an exception, then that will be caught and, and the exception object will be stored in the Future
The caller of get(endpoint)
can do this:
...
Future<Response> fr = myClassInstance.get(endpoint);
doSomethingElseConcurrentlyWithThe_makeGetRequest_call(...);
try {
Response r = fr.get();
...
} catch (Exception e) {
o.response.isException = true;
Log.d(TAG, e.getMessage());
}
How does lambda capture local static variable?
You don't need to capture global or static
variables. Only automatic variables have to be captured if you want to use them.
Because of that, yes, you can convert such lambda to a function pointer.
Cppreference:
The identifier in any capture without an initializer (other than the this-capture) is looked up using usual unqualified name lookup in the reaching scope of the lambda. The result of the lookup must be a variable with automatic storage duration declared in the reaching scope.
(emphasis mine)
"To capture" means to put a copy or a reference to a variable into a lambda object itself.
Global and static
variables have fixed memory location. You don't need to store copies or references to them to use them since their location is known at compile time and doesn't change.
(If you really want to have a copy of a global or static
variable, you can create it using named capture from C++14, which lets you create a custom member variable in a lambda object. But such capture is not necessary if you just want to use that global / static
variable.)
Automatic variables, on the other hand, don't have a fixed location. Multiple lambdas created at the exact same place could refer to different automatic variables. Because of that, a lambda object has to capture such variable - which means to contain either a reference to used automatic variable or a copy of it.
Related Topics
Why Do My Sfinae Expressions No Longer Work with Gcc 8.2
What Does the |= Operator Mean in C++
How to Wrap Functions with the '--Wrap' Option Correctly
Off-The-Shelf C++ Hex Dump Code
Best C++ Matrix Library for Sparse Unitary Matrices
In C++, Is There a Difference Between "Throw" and "Throw Ex"
Findwindow Does Not Find the a Window
C++ Cmake (Add Non-Built Files)
Non-Const Reference May Only Be Bound to an Lvalue
How to Assign Two Dimensional Array to **Pointer
Partial Template Specialization Based on "Signed-Ness" of Integer Type
Extern "C" Linkage Inside C++ Namespace
Communication Between Native-App and Chrome-Extension
How to Get Size of Check and Gap in Check Box
Are End+1 Iterators for Std::String Allowed
How to Turn on Multi-Cpu/Core C++ Compiles in the Visual Studio Ide (2008)