Reputation: 27633
I have a decent amount of code that relies on capturing a shared_from_this()
when using a lambda expression as a callback to ensure that my instance stays alive:
std::shared_ptr<Thing> self = shared_from_this();
auto doSomething = [this, self] ()
{
// various statements, none of which reference self, but do use this
}
So the question is: Since I am not referencing self
inside the lambda body, is a conformant compiler allowed to optimize the capture away?
Consider the following program:
#include <functional>
#include <iostream>
#include <memory>
std::function<void ()> gFunc;
struct S : std::enable_shared_from_this<S>
{
void putGlobal()
{
auto self = shared_from_this();
gFunc = [self] { };
}
};
int main()
{
auto x = std::make_shared<S>();
std::cout << x.use_count() << std::endl;
x->putGlobal();
std::cout << x.use_count() << std::endl;
}
The output is:
1
2
This indicates that g++-4.7.1
does not optimize the capture away (nor does clang-3.1
).
Upvotes: 30
Views: 3306
Reputation: 27633
The standard guarantees that captured values are not optimized away (per §5.1.2/14):
An entity is captured by copy if it is implicitly captured and the capture-default is = or if it is explicitly captured with a capture that does not include an &. For each entity captured by copy, an unnamed non- static data member is declared in the closure type. The declaration order of these members is unspecified. The type of such a data member is the type of the corresponding captured entity if the entity is not a reference to an object, or the referenced type otherwise.
So, self
is copied into the closure on evaluation (per §5.1.2/21):
When the lambda-expression is evaluated, the entities that are captured by copy are used to direct-initialize each corresponding non-static data member of the resulting closure object.
Upvotes: 35