问题
I can not quite understand an example from C++14 standard draft N4140 5.1.2.12 [expr.prim.lambda]
.
A lambda-expression with an associated capture-default that does not explicitly capture this or a variable with automatic storage duration (this excludes any id-expression that has been found to refer to an initcapture’s associated non-static data member), is said to implicitly capture the entity (i.e., this or a variable) if the compound-statement:
- odr-uses the entity, or
- names the entity in a potentially-evaluated expression where the enclosing full-expression depends on a generic lambda parameter declared within the reaching scope of the lambda-expression.
[ Example:
void f(int, const int (&)[2] = {}) { } // #1 void f(const int&, const int (&)[1]) { } // #2 void test() { const int x = 17; auto g = [](auto a) { f(x); // OK: calls #1, does not capture x }; auto g2 = [=](auto a) { int selector[sizeof(a) == 1 ? 1 : 2]{}; f(x, selector); // OK: is a dependent expression, so captures x }; }
—end example ]
All such implicitly captured entities shall be declared within the reaching scope of the lambda expression.
[ Note: The implicit capture of an entity by a nested lambda-expression can cause its implicit capture by the containing lambda-expression (see below). Implicit odr-uses of this can result in implicit capture. —end note ]
I thought that the beginning of a phrase a lambda-expression with an associated capture-default
should prohibit any implicit capture (and it's confirmed by comment), therefore #1
call will lead to an error (something about using not captured variable). So how it works? What will be first argument of f
? What if g
will be called after exiting test()
scope? What if I change #1
signature to void(const int&)
?
--
upd: Thanks to all for explanation of how it works. Later I'll try to find and post references to standard about this case.
回答1:
As T.C. said in his comment, #1 does not require a capture as x
is known at compile time and is therefore baked into the lambda. Not unlike how the function f
is known at compile time so it doesn't need to be captured.
I believe if you change f
's signature to int const &
you are now attempting to pass the address of the constant which is on the stack, thus subject to changes, and it would require capturing x
by value or reference.
来源:https://stackoverflow.com/questions/38750777/using-of-not-captured-variable-in-lambda