Reputation: 14119
Given the following program:
#include <iostream>
#include <memory>
using namespace std;
int main() {
std::shared_ptr<int> i(new int(42));
cout << i.use_count() << endl;
auto fn = [=](){i; cout << 42 << endl;};
cout << i.use_count() << endl;
return 0;
}
When does the compiler decide which objects it will capture?
The shared_ptr i
is never used in the lambda expression. So in a normal function I would assume that the optimizer will remove this nop statement.
But if it is removed the compiler could think that i
needs not to be captured.
So with gcc this program will always produce 1,2 as an output.
But is this guaranteed by the standard?
Upvotes: 4
Views: 2166
Reputation: 158559
If we go to cppreference page on lambda function they have the following explanation:
[=] captures all automatic variables mentioned in the body of the lambda by value
and further says:
The capture-list is a comma-separated list of zero or more captures, optionally beginning with the capture-default. The only capture defaults are & (implicitly catch the odr-used automatic variables and this by reference) and = (implicitly catch the odr-used automatic variables and this by value).
The reference section for odr-used says:
a variable is odr-used if its name appears as a potentially-evaluated expression, except if all of the following is true:
- applying lvalue-to-rvalue conversion to the exression yields a constant expression that doesn't invoke non-trivial functions
- the expression is either discarded-value expression or an lvalue-to-rvalue conversion
The exceptions do not apply to i
so i
will be captured.
Which agrees with the draft C++11 standard section 5.1.2
Lambda expressions paragraph 11 which says:
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; such entities shall be declared within the reaching scope of the lambda expression.
Upvotes: 2
Reputation: 254631
With a default-capture of [=]
, any local variable is captured if it's odr-used within the lambda. The definition of odr-used is:
A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression and the lvalue-to-rvalue conversion is immediately applied.
Here, i
is an evaluated expression, and isn't a constant; so it is odr-used
and therefore is captured; whether or not evaluating the expression has any effect.
But is this guaranteed by the standard?
tl;dr yes.
Upvotes: 2