Reputation: 510
I noticed that in project I worked on a lot of places where lambda expressions capture pointer on this, but doesn't use it. Does it lead to some kind overhead like pointer copy, or optimized by compiller?
void MyClass::SomeFunction()
{
...
grid->ForEachItem([this](const Item& item)
{
// Some code doesn't use this
}
}
And the same question dedicated to capture all by reference [&]
Upvotes: 1
Views: 1032
Reputation: 238311
Does it lead to some kind overhead like pointer copy
As far as the abstract machine is concerned: Yes. There will be a pointer copy, and the captured pointer will increase the size of the lambda object.
But if the compiler expands the function invokation inline, then all of that can be optimised to nothing.
And the same question dedicated to capture all by reference [&]
The capture-default will not capture anything that isn't used by the lambda, whether you use the value or reference capture.
Upvotes: 1
Reputation: 75688
I personally recommend not capturing this
if it is not used, but most certainly not because of performance reasons.
I will start with the obligatory note about performance: first and foremost write code for readability. And after you profile and identify a real problem, then you can think about optimizing the specific part of the code that is slow. Of course, I am not talking about algorithm complexity, but about micro optimizations.
In the case of lambda captures, the compiler is allowed to not actually capture objects that are not used, even if they are captured by copy [=]
. And on top of this, the fact that the lambda body is fully visible to the compiler coupled with the as if rule basically assure that on a modern compiler with optimizations enabled you don't need to worry performance-wise about what you capture.
However the reason I recommend against capturing something you don't use is for readability and expressivity of the expression. If the lambda uses this
or any other variable for that matter that is a reference or a pointer you need to make sure the lambda doesn't outlive what it captures. For instance if I see a lambda which captures this
and is returned outside of the method, I am very nervous and take extra care to make sure the object captured doesn't expire before the lambda can be called. And even if that is not a concern (e.g. the lambda doesn't escape outside of the method), the simple confusion of the reader ("this lambda should not use the state of the object, why then does it capture this
?") is enough of a compelling argument to avoid it.
When looking at the capture list of a lambda you should tell when it's safe to call it. The lambda lies if it captures a ref or a pointer to something it doesn't use. Don't write lying lambdas.
TLDR no overhead, but don't do it for readability and expressivity reasons.
Upvotes: 5