GCC seems to incorrectly capture global variables by reference in lambda functions, even when they are specified as 'capture by value'. This code will compile and print "a = 9":
#include <iostream>
int a = 10;
int main()
{
[=]() { a = 9; } ();
std::cout << "a = " << a << std::endl;
return 0;
}
While this code will not compile:
#include <iostream>
int main()
{
int a = 10;
[=]() { a = 9; } (); // error: assignment of member 'main()::<lambda()>::a' in read-only object
std::cout << "a = " << a << std::endl;
return 0;
}
But explicitly capturing a global by value and then assigning to it gives the error:
#include <iostream>
int a = 10;
int main()
{
[a]() { a = 9; } (); // assigment of read-only object
std::cout << "a = " << a << std::endl;
return 0;
}
I'm pretty sure that the error is the correct behaviour -- why does the implicit capture circumvent this error? I am just exploring the new C++11 features and accidentally wrote the first piece of code (not realizing it should be an error) and was then surprised when the modifications to what I assumed was a local variable affected the global.
Since it should be an error to assign to a captured-by-value variable in a lambda, GCC presumably uses a reference to the variable for optimization purposes, at least in this case, and doesn't detect the erroneous assignment.
§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.
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