Capturing References in C 11 Lambdas
In C , lambda expressions can capture variables from their enclosing scope. However, the method of capture determines whether the variable is accessed by reference or by value. Consider the following code:
<code class="cpp">#include <functional> #include <iostream> std::function<void()> make_function(int& x) { return [&]{ std::cout << x << std::endl; }; } int main() { int i = 3; auto f = make_function(i); i = 5; f(); }</code>
This code captures the variable x by reference using the [&] syntax. The question arises whether this program guarantees to output 5 without invoking undefined behavior.
Answer: Yes
The code is guaranteed to work correctly. Before examining the underlying standard wording, it is important to note that this code functions as intended by the C committee. However, the initial wording of the C 11 standard was unclear on this matter, leading to CWG issue 2011 being raised to provide clarification. This issue is being addressed in the ongoing development of the C standard.
Standard Explanation
According to [expr.prim.lambda]/17 of the C standard, only id-expressions referring to entities captured by copy are transformed into a member access on the lambda closure type. id-expressions referring to entities captured by reference are left alone and continue to denote the same entity they would have denoted in the enclosing scope.
In the code above, the captured entity is the parameter x of the make_function function, which falls within the reaching scope of the lambda. Therefore, the reference x in the lambda expression refers to the original variable declared in the main function.
It may initially appear problematic that x is being referenced outside its lifetime after the make_function function returns. However, there are limited scenarios in which a reference can be referenced outside its lifetime. Generally, a reference is either declared in scope or is a class member, in which case the class itself must be within its lifetime.
Therefore, the standard does not explicitly prohibit the use of references outside their lifetime. This loophole allowed for the capturing of references by reference in lambda expressions to be supported.
CWG Issue 2012 and Future Clarification
CWG issue 2012 was raised to address the oversight that references could be referenced outside their lifetime under certain circumstances. The resolution of this issue inadvertently affected the specification for lambda capture by reference of references. However, it is expected that this regression will be fixed before the release of C 17.
The above is the detailed content of Can C 11 Lambdas Capture References Without Invoking Undefined Behavior?. For more information, please follow other related articles on the PHP Chinese website!