Disadvantage of using lambda default capture by value or reference in C ++ 11?

What are the pitfalls of using lambda default capture by value ( [=] ) or by reference ( [&] ) in C ++ 11?

I know some pitfalls like:

  • If the lifetime of a closure created from lambda exceeds the lifetime of a local variable, will the link in the closure hang?

Are there any default flaws for capturing by value?

+6
source share
4 answers

I think the dangling link issue you mentioned is the main trap.

However, another thing that is sometimes overlooked is that even if the capture-by-value-lambda function is used in a member function, it does not create a copy of the member variables used, but only makes a copy of the this pointer.

Firstly, it means that you are open again for the problem with the dangling pointer, and secondly, you can accidentally change variables outside the lambda area, even if it looks like you are only changing the local copy.

eg. this will print 0 1 1 instead of 0 1 0

 struct Foo { int bar=0; int bas() { auto inc = [=]() { bar++; //this is equivalent to this->bar++ return bar; }; return inc(); } }; int main() { Foo foo; std::cout << foo.bar <<" "; std::cout << foo.bas() << " "; std::cout << foo.bar << std::endl; } 

EDIT: Just to avoid the confusion associated with the point made by @Snps:
If bar was a local variable in bas() (and therefore was fixed by value), the aforementioned lambda will not compile, since the value-captured variables are constant by default, unless you explicitly specify the lambda as mutable. Therefore, if you think about it, it is clear that the bar is not copied, but it is easily forgotten when reading or writing code.

+7
source

It has the same advantages and disadvantages as comparison:

 int value(const T x) { ... } int value(T& x) { ... } 
+3
source

Capturing by value using [=] or [<identifier>] creates a lambda element of the same type as a captured object, including a constant, for example, when capturing const int by value, the resulting member cannot be mutated, even if the lambda operator call changed.

 const int i = 1; [=] () mutable { ++i; }(); // Error: increment of read-only variable. 

This can be circumvented using expressions to initialize C ++ 14:

 [i = i] () mutable { ++i; }(); // Ok 
+3
source

Capturing with values ​​implies copying private values, so this can mean more memory consumption and more processing for this copy.

+1
source

Source: https://habr.com/ru/post/1239677/


All Articles